package jdk.javadoc.internal.doclets.formats.html;
import jdk.javadoc.internal.doclets.formats.html.markup.Head;
import java.io.*;
import java.util.List;
import javax.lang.model.element.Element;
import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.FileObject;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.Messages;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
public class SourceToHTMLConverter {
private static final int NUM_BLANK_LINES = 60;
private static final String NEW_LINE = DocletConstants.NL;
private final HtmlConfiguration configuration;
private final Messages messages;
private final Resources resources;
private final Utils utils;
private final DocletEnvironment docEnv;
private final DocPath outputdir;
private DocPath relativePath = DocPath.empty;
private SourceToHTMLConverter(HtmlConfiguration configuration, DocletEnvironment rd,
DocPath outputdir) {
this.configuration = configuration;
this.messages = configuration.getMessages();
this.resources = configuration.resources;
this.utils = configuration.utils;
this.docEnv = rd;
this.outputdir = outputdir;
}
public static void convertRoot(HtmlConfiguration configuration, DocletEnvironment docEnv,
DocPath outputdir) throws DocFileIOException, SimpleDocletException {
new SourceToHTMLConverter(configuration, docEnv, outputdir).generate();
}
void generate() throws DocFileIOException, SimpleDocletException {
if (docEnv == null || outputdir == null) {
return;
}
for (ModuleElement mdl : configuration.getSpecifiedModuleElements()) {
if (!(configuration.nodeprecated && utils.isDeprecated(mdl)))
convertModule(mdl, outputdir);
}
for (PackageElement pkg : configuration.getSpecifiedPackageElements()) {
if (!(configuration.nodeprecated && utils.isDeprecated(pkg)))
convertPackage(pkg, outputdir);
}
for (TypeElement te : configuration.getSpecifiedTypeElements()) {
if (!(configuration.nodeprecated &&
(utils.isDeprecated(te) || utils.isDeprecated(utils.containingPackage(te)))))
convertClass(te, outputdir);
}
}
public void convertPackage(PackageElement pkg, DocPath outputdir)
throws DocFileIOException, SimpleDocletException {
if (pkg == null) {
return;
}
for (Element te : utils.getAllClasses(pkg)) {
if (!(configuration.nodeprecated && utils.isDeprecated(te)))
convertClass((TypeElement)te, outputdir);
}
}
public void convertModule(ModuleElement mdl, DocPath outputdir)
throws DocFileIOException, SimpleDocletException {
if (mdl == null) {
return;
}
for (Element elem : mdl.getEnclosedElements()) {
if (elem instanceof PackageElement && configuration.docEnv.isIncluded(elem)
&& !(configuration.nodeprecated && utils.isDeprecated(elem))) {
convertPackage((PackageElement) elem, outputdir);
}
}
}
public void convertClass(TypeElement te, DocPath outputdir)
throws DocFileIOException, SimpleDocletException {
if (te == null) {
return;
}
FileObject fo = utils.getFileObject(te);
if (fo == null)
return;
try {
Reader r = fo.openReader(true);
int lineno = 1;
String line;
relativePath = DocPaths.SOURCE_OUTPUT
.resolve(configuration.docPaths.forPackage(te))
.invert();
Content body = getHeader();
Content pre = new HtmlTree(HtmlTag.PRE);
try (LineNumberReader reader = new LineNumberReader(r)) {
while ((line = reader.readLine()) != null) {
addLineNo(pre, lineno);
addLine(pre, line, lineno);
lineno++;
}
}
addBlankLines(pre);
Content div = HtmlTree.DIV(HtmlStyle.sourceContainer, pre);
body.add(HtmlTree.MAIN(div));
writeToFile(body, outputdir.resolve(configuration.docPaths.forClass(te)), te);
} catch (IOException e) {
String message = resources.getText("doclet.exception.read.file", fo.getName());
throw new SimpleDocletException(message, e);
}
}
private void writeToFile(Content body, DocPath path, TypeElement te) throws DocFileIOException {
Head head = new Head(path, configuration.docletVersion)
.setTitle(resources.getText("doclet.Window_Source_title"))
.setDescription(HtmlDocletWriter.getDescription("source", te))
.setGenerator(HtmlDocletWriter.getGenerator(getClass()))
.addDefaultScript(false)
.setStylesheets(configuration.getMainStylesheet(), configuration.getAdditionalStylesheets());
Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
head.toContent(), body);
HtmlDocument htmlDocument = new HtmlDocument(htmlTree);
messages.notice("doclet.Generating_0", path.getPath());
htmlDocument.write(DocFile.createFileForOutput(configuration, path));
}
public void addStyleSheetProperties(Content head) {
String filename = configuration.stylesheetfile;
DocPath stylesheet;
if (filename.length() > 0) {
DocFile file = DocFile.createFileForInput(configuration, filename);
stylesheet = DocPath.create(file.getName());
} else {
stylesheet = DocPaths.STYLESHEET;
}
DocPath p = relativePath.resolve(stylesheet);
HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", p.getPath(), "Style");
head.add(link);
addStylesheets(head);
}
protected void addStylesheets(Content tree) {
List<String> stylesheets = configuration.additionalStylesheets;
if (!stylesheets.isEmpty()) {
stylesheets.forEach((ssheet) -> {
DocFile file = DocFile.createFileForInput(configuration, ssheet);
DocPath ssheetPath = DocPath.create(file.getName());
HtmlTree slink = HtmlTree.LINK("stylesheet", "text/css", relativePath.resolve(ssheetPath).getPath(),
"Style");
tree.add(slink);
});
}
}
private static Content getHeader() {
return new HtmlTree(HtmlTag.BODY).put(HtmlAttr.CLASS, "source");
}
private static void addLineNo(Content pre, int lineno) {
HtmlTree span = new HtmlTree(HtmlTag.SPAN);
span.setStyle(HtmlStyle.sourceLineNo);
if (lineno < 10) {
span.add("00" + Integer.toString(lineno));