AbstractDoclet.java revision 3294:9adfb22ff08f
1219019Sgabor/*
2219019Sgabor * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3219019Sgabor * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4219019Sgabor *
5219019Sgabor * This code is free software; you can redistribute it and/or modify it
6219019Sgabor * under the terms of the GNU General Public License version 2 only, as
7219019Sgabor * published by the Free Software Foundation.  Oracle designates this
8219019Sgabor * particular file as subject to the "Classpath" exception as provided
9219019Sgabor * by Oracle in the LICENSE file that accompanied this code.
10219019Sgabor *
11219019Sgabor * This code is distributed in the hope that it will be useful, but WITHOUT
12219019Sgabor * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13219019Sgabor * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14219019Sgabor * version 2 for more details (a copy is included in the LICENSE file that
15219019Sgabor * accompanied this code).
16219019Sgabor *
17219019Sgabor * You should have received a copy of the GNU General Public License version
18219019Sgabor * 2 along with this work; if not, write to the Free Software Foundation,
19219019Sgabor * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20219019Sgabor *
21219019Sgabor * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22219019Sgabor * or visit www.oracle.com if you need additional information or have any
23219019Sgabor * questions.
24219019Sgabor */
25219019Sgabor
26219019Sgaborpackage jdk.javadoc.internal.doclets.toolkit;
27219019Sgabor
28219019Sgaborimport java.util.SortedSet;
29219019Sgaborimport java.util.TreeSet;
30219019Sgabor
31219019Sgaborimport javax.lang.model.SourceVersion;
32219019Sgaborimport javax.lang.model.element.PackageElement;
33219019Sgaborimport javax.lang.model.element.TypeElement;
34219019Sgabor
35219019Sgaborimport jdk.javadoc.doclet.DocletEnvironment;
36219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder;
37219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory;
38219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
39219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
40219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
41219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter;
42219019Sgaborimport jdk.javadoc.internal.doclets.toolkit.util.Utils;
43219019Sgabor
44219019Sgaborimport static javax.tools.Diagnostic.Kind.*;
45219019Sgabor
46219019Sgabor/**
47219019Sgabor * An abstract implementation of a Doclet.
48219019Sgabor *
49219019Sgabor *  <p><b>This is NOT part of any supported API.
50219019Sgabor *  If you write code that depends on this, you do so at your own risk.
51219019Sgabor *  This code and its internal interfaces are subject to change or
52219019Sgabor *  deletion without notice.</b>
53219019Sgabor *
54219019Sgabor * @author Jamie Ho
55219019Sgabor */
56219019Sgaborpublic abstract class AbstractDoclet {
57219019Sgabor
58219019Sgabor    /**
59219019Sgabor     * The global configuration information for this run.
60219019Sgabor     */
61219019Sgabor    public Configuration configuration;
62219019Sgabor    /*
63219019Sgabor     *  a handle to our utility methods
64219019Sgabor     */
65219019Sgabor    protected Utils utils;
66219019Sgabor
67219019Sgabor    /**
68219019Sgabor     * The only doclet that may use this toolkit is {@value}
69219019Sgabor     */
70219019Sgabor    private static final String TOOLKIT_DOCLET_NAME =
71219019Sgabor        jdk.javadoc.internal.doclets.formats.html.HtmlDoclet.class.getName();
72219019Sgabor
73219019Sgabor    /**
74219019Sgabor     * Verify that the only doclet that is using this toolkit is
75219019Sgabor     * {@value #TOOLKIT_DOCLET_NAME}.
76219019Sgabor     */
77219019Sgabor    private boolean isValidDoclet() {
78219019Sgabor        if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
79219019Sgabor            configuration.message.error("doclet.Toolkit_Usage_Violation",
80219019Sgabor                TOOLKIT_DOCLET_NAME);
81219019Sgabor            return false;
82219019Sgabor        }
83219019Sgabor        return true;
84219019Sgabor    }
85219019Sgabor
86219019Sgabor    /**
87219019Sgabor     * The method that starts the execution of the doclet.
88219019Sgabor     *
89219019Sgabor     * @param root   the {@link DocletEnvironment} that points to the source to document.
90219019Sgabor     * @return true if the doclet executed without error.  False otherwise.
91219019Sgabor     */
92219019Sgabor    public boolean startDoclet(DocletEnvironment root) {
93219019Sgabor        configuration = configuration();
94219019Sgabor        configuration.root = root;
95219019Sgabor        configuration.cmtUtils = new CommentUtils(configuration);
96219019Sgabor        configuration.utils = new Utils(configuration);
97219019Sgabor        utils = configuration.utils;
98219019Sgabor        configuration.workArounds = new WorkArounds(configuration);
99219019Sgabor        if (!isValidDoclet()) {
100219019Sgabor            return false;
101219019Sgabor        }
102219019Sgabor
103219019Sgabor        try {
104219019Sgabor            startGeneration(root);
105219019Sgabor        } catch (Configuration.Fault f) {
106219019Sgabor            configuration.reporter.print(ERROR, f.getMessage());
107219019Sgabor            return false;
108219019Sgabor        } catch (DocletAbortException e) {
109219019Sgabor            Throwable cause = e.getCause();
110219019Sgabor            if (cause != null) {
111219019Sgabor                if (cause.getLocalizedMessage() != null) {
112219019Sgabor                    configuration.reporter.print(ERROR, cause.getLocalizedMessage());
113219019Sgabor                } else {
114219019Sgabor                    configuration.reporter.print(ERROR, cause.toString());
115219019Sgabor                }
116219019Sgabor            }
117219019Sgabor            return false;
118219019Sgabor        } catch (Exception exc) {
119219019Sgabor            return false;
120219019Sgabor        }
121219019Sgabor        return true;
122219019Sgabor    }
123219019Sgabor
124219019Sgabor    /**
125219019Sgabor     * Returns the SourceVersion indicating the features supported by this doclet.
126219019Sgabor     * @return SourceVersion
127219019Sgabor     */
128219019Sgabor    public SourceVersion sourceVersion() {
129219019Sgabor        return SourceVersion.RELEASE_8;
130219019Sgabor    }
131219019Sgabor
132219019Sgabor
133219019Sgabor    /**
134219019Sgabor     * Create the configuration instance and returns it.
135219019Sgabor     * @return the configuration of the doclet.
136219019Sgabor     */
137219019Sgabor    public abstract Configuration configuration();
138219019Sgabor
139219019Sgabor    /**
140219019Sgabor     * Start the generation of files. Call generate methods in the individual
141219019Sgabor     * writers, which will in turn generate the documentation files. Call the
142219019Sgabor     * TreeWriter generation first to ensure the Class Hierarchy is built
143219019Sgabor     * first and then can be used in the later generation.
144219019Sgabor     *
145219019Sgabor     * @see jdk.doclet.DocletEnvironment
146219019Sgabor     */
147219019Sgabor    private void startGeneration(DocletEnvironment root) throws Configuration.Fault, Exception {
148219019Sgabor        if (root.getIncludedClasses().isEmpty()) {
149219019Sgabor            configuration.message.
150219019Sgabor                error("doclet.No_Public_Classes_To_Document");
151219019Sgabor            return;
152219019Sgabor        }
153219019Sgabor        if (!configuration.setOptions()) {
154219019Sgabor            return;
155219019Sgabor        }
156219019Sgabor        configuration.getDocletSpecificMsg().notice("doclet.build_version",
157219019Sgabor            configuration.getDocletSpecificBuildDate());
158219019Sgabor        ClassTree classtree = new ClassTree(configuration, configuration.nodeprecated);
159219019Sgabor
160219019Sgabor        generateClassFiles(root, classtree);
161219019Sgabor        configuration.utils.copyDocFiles(DocPaths.DOC_FILES);
162219019Sgabor
163219019Sgabor        PackageListWriter.generate(configuration);
164219019Sgabor        generatePackageFiles(classtree);
165219019Sgabor        generateModuleFiles();
166219019Sgabor
167219019Sgabor        generateOtherFiles(root, classtree);
168219019Sgabor        configuration.tagletManager.printReport();
169219019Sgabor    }
170219019Sgabor
171219019Sgabor    /**
172219019Sgabor     * Generate additional documentation that is added to the API documentation.
173219019Sgabor     *
174219019Sgabor     * @param root     the DocletEnvironment of source to document.
175219019Sgabor     * @param classtree the data structure representing the class tree.
176219019Sgabor     */
177219019Sgabor    protected void generateOtherFiles(DocletEnvironment root, ClassTree classtree) throws Exception {
178219019Sgabor        BuilderFactory builderFactory = configuration.getBuilderFactory();
179219019Sgabor        AbstractBuilder constantsSummaryBuilder = builderFactory.getConstantsSummaryBuilder();
180219019Sgabor        constantsSummaryBuilder.build();
181219019Sgabor        AbstractBuilder serializedFormBuilder = builderFactory.getSerializedFormBuilder();
182219019Sgabor        serializedFormBuilder.build();
183219019Sgabor    }
184219019Sgabor
185219019Sgabor    /**
186219019Sgabor     * Generate the module documentation.
187219019Sgabor     *
188219019Sgabor     */
189219019Sgabor    protected abstract void generateModuleFiles() throws Exception;
190219019Sgabor
191219019Sgabor    /**
192219019Sgabor     * Generate the package documentation.
193219019Sgabor     *
194219019Sgabor     * @param classtree the data structure representing the class tree.
195219019Sgabor     */
196219019Sgabor    protected abstract void generatePackageFiles(ClassTree classtree) throws Exception;
197219019Sgabor
198219019Sgabor    /**
199219019Sgabor     * Generate the class documentation.
200219019Sgabor     *
201219019Sgabor     * @param classtree the data structure representing the class tree.
202219019Sgabor     */
203219019Sgabor    protected abstract void generateClassFiles(SortedSet<TypeElement> arr, ClassTree classtree);
204219019Sgabor
205219019Sgabor    /**
206219019Sgabor     * Iterate through all classes and construct documentation for them.
207219019Sgabor     *
208219019Sgabor     * @param root      the DocletEnvironment of source to document.
209219019Sgabor     * @param classtree the data structure representing the class tree.
210219019Sgabor     */
211219019Sgabor    protected void generateClassFiles(DocletEnvironment root, ClassTree classtree) {
212219019Sgabor        generateClassFiles(classtree);
213219019Sgabor        SortedSet<PackageElement> packages = new TreeSet<>(utils.makePackageComparator());
214219019Sgabor        packages.addAll(utils.getSpecifiedPackages());
215219019Sgabor        packages.stream().forEach((pkg) -> {
216219019Sgabor            generateClassFiles(utils.getAllClasses(pkg), classtree);
217219019Sgabor        });
218219019Sgabor    }
219219019Sgabor
220219019Sgabor    /**
221219019Sgabor     * Generate the class files for single classes specified on the command line.
222219019Sgabor     *
223219019Sgabor     * @param classtree the data structure representing the class tree.
224219019Sgabor     */
225219019Sgabor    private void generateClassFiles(ClassTree classtree) {
226219019Sgabor        SortedSet<PackageElement> packages = configuration.typeElementCatalog.packages();
227219019Sgabor        packages.stream().forEach((pkg) -> {
228219019Sgabor            generateClassFiles(configuration.typeElementCatalog.allClasses(pkg), classtree);
229219019Sgabor        });
230219019Sgabor    }
231219019Sgabor}
232219019Sgabor