--- old/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Fri Jan 22 12:17:50 2016 +++ /dev/null Fri Jan 22 12:17:50 2016 @@ -1,2227 +0,0 @@ -/* - * Copyright (c) 1998, 2015, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.tools.doclets.formats.html; - -import java.io.*; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.sun.javadoc.*; -import com.sun.tools.doclets.formats.html.markup.*; -import com.sun.tools.doclets.internal.toolkit.*; -import com.sun.tools.doclets.internal.toolkit.taglets.*; -import com.sun.tools.doclets.internal.toolkit.util.*; -import com.sun.tools.javac.util.StringUtils; - -/** - * Class for the Html Format Code Generation specific to JavaDoc. - * This Class contains methods related to the Html Code Generation which - * are used extensively while generating the entire documentation. - * - *
This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - * - * @since 1.2 - * @author Atul M Dambalkar - * @author Robert Field - * @author Bhavesh Patel (Modified) - */ -public class HtmlDocletWriter extends HtmlDocWriter { - - /** - * Relative path from the file getting generated to the destination - * directory. For example, if the file getting generated is - * "java/lang/Object.html", then the path to the root is "../..". - * This string can be empty if the file getting generated is in - * the destination directory. - */ - public final DocPath pathToRoot; - - /** - * Platform-independent path from the current or the - * destination directory to the file getting generated. - * Used when creating the file. - */ - public final DocPath path; - - /** - * Name of the file getting generated. If the file getting generated is - * "java/lang/Object.html", then the filename is "Object.html". - */ - public final DocPath filename; - - /** - * The global configuration information for this run. - */ - public final ConfigurationImpl configuration; - - protected final Utils utils; - - /** - * To check whether annotation heading is printed or not. - */ - protected boolean printedAnnotationHeading = false; - - /** - * To check whether annotation field heading is printed or not. - */ - protected boolean printedAnnotationFieldHeading = false; - - /** - * To check whether the repeated annotations is documented or not. - */ - private boolean isAnnotationDocumented = false; - - /** - * To check whether the container annotations is documented or not. - */ - private boolean isContainerDocumented = false; - - HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV); - - /** - * Constructor to construct the HtmlStandardWriter object. - * - * @param path File to be generated. - */ - public HtmlDocletWriter(ConfigurationImpl configuration, DocPath path) - throws IOException { - super(configuration, path); - this.configuration = configuration; - this.utils = configuration.utils; - this.path = path; - this.pathToRoot = path.parent().invert(); - this.filename = path.basename(); - } - - /** - * Replace {@docRoot} tag used in options that accept HTML text, such - * as -header, -footer, -top and -bottom, and when converting a relative - * HREF where commentTagsToString inserts a {@docRoot} where one was - * missing. (Also see DocRootTaglet for {@docRoot} tags in doc - * comments.) - *
- * Replace {@docRoot} tag in htmlstr with the relative path to the - * destination directory from the directory where the file is being - * written, looping to handle all such tags in htmlstr. - *
- * For example, for "-d docs" and -header containing {@docRoot}, when - * the HTML page for source file p/C1.java is being generated, the - * {@docRoot} tag would be inserted into the header as "../", - * the relative path from docs/p/ to docs/ (the document root). - *
- * Note: This doc comment was written with '@' representing '@'
- * to prevent the inline tag from being interpreted.
- */
- public String replaceDocRootDir(String htmlstr) {
- // Return if no inline tags exist
- int index = htmlstr.indexOf("{@");
- if (index < 0) {
- return htmlstr;
- }
- Matcher docrootMatcher = docrootPattern.matcher(htmlstr);
- if (!docrootMatcher.find()) {
- return htmlstr;
- }
- StringBuilder buf = new StringBuilder();
- int prevEnd = 0;
- do {
- int match = docrootMatcher.start();
- // append htmlstr up to start of next {@docroot}
- buf.append(htmlstr.substring(prevEnd, match));
- prevEnd = docrootMatcher.end();
- if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", prevEnd)) {
- // Insert the absolute link if {@docRoot} is followed by "/..".
- buf.append(configuration.docrootparent);
- prevEnd += 3;
- } else {
- // Insert relative path where {@docRoot} was located
- buf.append(pathToRoot.isEmpty() ? "." : pathToRoot.getPath());
- }
- // Append slash if next character is not a slash
- if (prevEnd < htmlstr.length() && htmlstr.charAt(prevEnd) != '/') {
- buf.append('/');
- }
- } while (docrootMatcher.find());
- buf.append(htmlstr.substring(prevEnd));
- return buf.toString();
- }
- //where:
- // Note: {@docRoot} is not case sensitive when passed in w/command line option:
- private static final Pattern docrootPattern =
- Pattern.compile(Pattern.quote("{@docroot}"), Pattern.CASE_INSENSITIVE);
-
- /**
- * Get the script to show or hide the All classes link.
- *
- * @param id id of the element to show or hide
- * @return a content tree for the script
- */
- public Content getAllClassesLinkScript(String id) {
- HtmlTree script = HtmlTree.SCRIPT();
- String scriptCode = "" + DocletConstants.NL;
- Content scriptContent = new RawHtml(scriptCode);
- script.addContent(scriptContent);
- Content div = HtmlTree.DIV(script);
- Content div_noscript = HtmlTree.DIV(getResource("doclet.No_Script_Message"));
- Content noScript = HtmlTree.NOSCRIPT(div_noscript);
- div.addContent(noScript);
- return div;
- }
-
- /**
- * Add method information.
- *
- * @param method the method to be documented
- * @param dl the content tree to which the method information will be added
- */
- private void addMethodInfo(MethodDoc method, Content dl) {
- ClassDoc[] intfacs = method.containingClass().interfaces();
- MethodDoc overriddenMethod = method.overriddenMethod();
- // Check whether there is any implementation or overridden info to be
- // printed. If no overridden or implementation info needs to be
- // printed, do not print this section.
- if ((intfacs.length > 0 &&
- new ImplementedMethods(method, this.configuration).build().length > 0) ||
- overriddenMethod != null) {
- MethodWriterImpl.addImplementsInfo(this, method, dl);
- if (overriddenMethod != null) {
- MethodWriterImpl.addOverridden(this,
- method.overriddenType(), overriddenMethod, dl);
- }
- }
- }
-
- /**
- * Adds the tags information.
- *
- * @param doc the doc for which the tags will be generated
- * @param htmltree the documentation tree to which the tags will be added
- */
- protected void addTagsInfo(Doc doc, Content htmltree) {
- if (configuration.nocomment) {
- return;
- }
- Content dl = new HtmlTree(HtmlTag.DL);
- if (doc instanceof MethodDoc) {
- addMethodInfo((MethodDoc) doc, dl);
- }
- Content output = new ContentBuilder();
- TagletWriter.genTagOuput(configuration.tagletManager, doc,
- configuration.tagletManager.getCustomTaglets(doc),
- getTagletWriterInstance(false), output);
- dl.addContent(output);
- htmltree.addContent(dl);
- }
-
- /**
- * Check whether there are any tags for Serialization Overview
- * section to be printed.
- *
- * @param field the FieldDoc object to check for tags.
- * @return true if there are tags to be printed else return false.
- */
- protected boolean hasSerializationOverviewTags(FieldDoc field) {
- Content output = new ContentBuilder();
- TagletWriter.genTagOuput(configuration.tagletManager, field,
- configuration.tagletManager.getCustomTaglets(field),
- getTagletWriterInstance(false), output);
- return !output.isEmpty();
- }
-
- /**
- * Returns a TagletWriter that knows how to write HTML.
- *
- * @return a TagletWriter that knows how to write HTML.
- */
- public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
- return new TagletWriterImpl(this, isFirstSentence);
- }
-
- /**
- * Get Package link, with target frame.
- *
- * @param pd The link will be to the "package-summary.html" page for this package
- * @param target name of the target frame
- * @param label tag for the link
- * @return a content for the target package link
- */
- public Content getTargetPackageLink(PackageDoc pd, String target,
- Content label) {
- return getHyperLink(pathString(pd, DocPaths.PACKAGE_SUMMARY), label, "", target);
- }
-
- /**
- * Get Profile Package link, with target frame.
- *
- * @param pd the packageDoc object
- * @param target name of the target frame
- * @param label tag for the link
- * @param profileName the name of the profile being documented
- * @return a content for the target profile packages link
- */
- public Content getTargetProfilePackageLink(PackageDoc pd, String target,
- Content label, String profileName) {
- return getHyperLink(pathString(pd, DocPaths.profilePackageSummary(profileName)),
- label, "", target);
- }
-
- /**
- * Get Profile link, with target frame.
- *
- * @param target name of the target frame
- * @param label tag for the link
- * @param profileName the name of the profile being documented
- * @return a content for the target profile link
- */
- public Content getTargetProfileLink(String target, Content label,
- String profileName) {
- return getHyperLink(pathToRoot.resolve(
- DocPaths.profileSummary(profileName)), label, "", target);
- }
-
- /**
- * Get the type name for profile search.
- *
- * @param cd the classDoc object for which the type name conversion is needed
- * @return a type name string for the type
- */
- public String getTypeNameForProfile(ClassDoc cd) {
- StringBuilder typeName =
- new StringBuilder((cd.containingPackage()).name().replace(".", "/"));
- typeName.append("/")
- .append(cd.name().replace(".", "$"));
- return typeName.toString();
- }
-
- /**
- * Check if a type belongs to a profile.
- *
- * @param cd the classDoc object that needs to be checked
- * @param profileValue the profile in which the type needs to be checked
- * @return true if the type is in the profile
- */
- public boolean isTypeInProfile(ClassDoc cd, int profileValue) {
- return (configuration.profiles.getProfile(getTypeNameForProfile(cd)) <= profileValue);
- }
-
- public void addClassesSummary(ClassDoc[] classes, String label,
- String tableSummary, String[] tableHeader, Content summaryContentTree,
- int profileValue) {
- if(classes.length > 0) {
- Arrays.sort(classes);
- Content caption = getTableCaption(new RawHtml(label));
- Content table = (configuration.isOutputHtml5())
- ? HtmlTree.TABLE(HtmlStyle.typeSummary, caption)
- : HtmlTree.TABLE(HtmlStyle.typeSummary, tableSummary, caption);
- table.addContent(getSummaryTableHeader(tableHeader, "col"));
- Content tbody = new HtmlTree(HtmlTag.TBODY);
- for (int i = 0; i < classes.length; i++) {
- if (!isTypeInProfile(classes[i], profileValue)) {
- continue;
- }
- if (!utils.isCoreClass(classes[i]) ||
- !configuration.isGeneratedDoc(classes[i])) {
- continue;
- }
- Content classContent = getLink(new LinkInfoImpl(
- configuration, LinkInfoImpl.Kind.PACKAGE, classes[i]));
- Content tdClass = HtmlTree.TD(HtmlStyle.colFirst, classContent);
- HtmlTree tr = HtmlTree.TR(tdClass);
- if (i%2 == 0)
- tr.addStyle(HtmlStyle.altColor);
- else
- tr.addStyle(HtmlStyle.rowColor);
- HtmlTree tdClassDescription = new HtmlTree(HtmlTag.TD);
- tdClassDescription.addStyle(HtmlStyle.colLast);
- if (utils.isDeprecated(classes[i])) {
- tdClassDescription.addContent(deprecatedLabel);
- if (classes[i].tags("deprecated").length > 0) {
- addSummaryDeprecatedComment(classes[i],
- classes[i].tags("deprecated")[0], tdClassDescription);
- }
- }
- else
- addSummaryComment(classes[i], tdClassDescription);
- tr.addContent(tdClassDescription);
- tbody.addContent(tr);
- }
- table.addContent(tbody);
- summaryContentTree.addContent(table);
- }
- }
-
- /**
- * Generates the HTML document tree and prints it out.
- *
- * @param metakeywords Array of String keywords for META tag. Each element
- * of the array is assigned to a separate META tag.
- * Pass in null for no array
- * @param includeScript true if printing windowtitle script
- * false for files that appear in the left-hand frames
- * @param body the body htmltree to be included in the document
- */
- public void printHtmlDocument(String[] metakeywords, boolean includeScript,
- Content body) throws IOException {
- Content htmlDocType = configuration.isOutputHtml5()
- ? DocType.HTML5
- : DocType.TRANSITIONAL;
- Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
- Content head = new HtmlTree(HtmlTag.HEAD);
- head.addContent(getGeneratedBy(!configuration.notimestamp));
- head.addContent(getTitle());
- Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE,
- (configuration.charset.length() > 0) ?
- configuration.charset : HtmlConstants.HTML_DEFAULT_CHARSET);
- head.addContent(meta);
- if (!configuration.notimestamp) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
- meta = HtmlTree.META(configuration.isOutputHtml5()
- ? "dc.created"
- : "date", dateFormat.format(new Date()));
- head.addContent(meta);
- }
- if (metakeywords != null) {
- for (String metakeyword : metakeywords) {
- meta = HtmlTree.META("keywords", metakeyword);
- head.addContent(meta);
- }
- }
- addStyleSheetProperties(head);
- addScriptProperties(head);
- Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
- head, body);
- Content htmlDocument = new HtmlDocument(htmlDocType,
- htmlComment, htmlTree);
- write(htmlDocument);
- }
-
- /**
- * Get the window title.
- *
- * @param title the title string to construct the complete window title
- * @return the window title string
- */
- public String getWindowTitle(String title) {
- if (configuration.windowtitle.length() > 0) {
- title += " (" + configuration.windowtitle + ")";
- }
- return title;
- }
-
- /**
- * Get user specified header and the footer.
- *
- * @param header if true print the user provided header else print the
- * user provided footer.
- */
- public Content getUserHeaderFooter(boolean header) {
- String content;
- if (header) {
- content = replaceDocRootDir(configuration.header);
- } else {
- if (configuration.footer.length() != 0) {
- content = replaceDocRootDir(configuration.footer);
- } else {
- content = replaceDocRootDir(configuration.header);
- }
- }
- Content rawContent = new RawHtml(content);
- return rawContent;
- }
-
- /**
- * Adds the user specified top.
- *
- * @param htmlTree the content tree to which user specified top will be added
- */
- public void addTop(Content htmlTree) {
- Content top = new RawHtml(replaceDocRootDir(configuration.top));
- fixedNavDiv.addContent(top);
- }
-
- /**
- * Adds the user specified bottom.
- *
- * @param htmlTree the content tree to which user specified bottom will be added
- */
- public void addBottom(Content htmlTree) {
- Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom));
- Content small = HtmlTree.SMALL(bottom);
- Content p = HtmlTree.P(HtmlStyle.legalCopy, small);
- htmlTree.addContent(p);
- }
-
- /**
- * Adds the navigation bar for the Html page at the top and and the bottom.
- *
- * @param header If true print navigation bar at the top of the page else
- * @param htmlTree the HtmlTree to which the nav links will be added
- */
- protected void addNavLinks(boolean header, Content htmlTree) {
- if (!configuration.nonavbar) {
- Content tree = (configuration.allowTag(HtmlTag.NAV))
- ? HtmlTree.NAV()
- : htmlTree;
- String allClassesId = "allclasses_";
- HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
- fixedNavDiv.addStyle(HtmlStyle.fixedNav);
- Content skipNavLinks = configuration.getResource("doclet.Skip_navigation_links");
- if (header) {
- fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
- navDiv.addStyle(HtmlStyle.topNav);
- allClassesId += "navbar_top";
- Content a = getMarkerAnchor(SectionName.NAVBAR_TOP);
- //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
- navDiv.addContent(a);
- Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
- getDocLink(SectionName.SKIP_NAVBAR_TOP), skipNavLinks,
- skipNavLinks.toString(), ""));
- navDiv.addContent(skipLinkContent);
- } else {
- tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
- navDiv.addStyle(HtmlStyle.bottomNav);
- allClassesId += "navbar_bottom";
- Content a = getMarkerAnchor(SectionName.NAVBAR_BOTTOM);
- navDiv.addContent(a);
- Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
- getDocLink(SectionName.SKIP_NAVBAR_BOTTOM), skipNavLinks,
- skipNavLinks.toString(), ""));
- navDiv.addContent(skipLinkContent);
- }
- if (header) {
- navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
- } else {
- navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
- }
- HtmlTree navList = new HtmlTree(HtmlTag.UL);
- navList.addStyle(HtmlStyle.navList);
- navList.addAttr(HtmlAttr.TITLE,
- configuration.getText("doclet.Navigation"));
- if (configuration.createoverview) {
- navList.addContent(getNavLinkContents());
- }
- if (configuration.packages.size() == 1) {
- navList.addContent(getNavLinkPackage(configuration.packages.first()));
- } else if (configuration.packages.size() > 1) {
- navList.addContent(getNavLinkPackage());
- }
- navList.addContent(getNavLinkClass());
- if(configuration.classuse) {
- navList.addContent(getNavLinkClassUse());
- }
- if(configuration.createtree) {
- navList.addContent(getNavLinkTree());
- }
- if(!(configuration.nodeprecated ||
- configuration.nodeprecatedlist)) {
- navList.addContent(getNavLinkDeprecated());
- }
- if(configuration.createindex) {
- navList.addContent(getNavLinkIndex());
- }
- if (!configuration.nohelp) {
- navList.addContent(getNavLinkHelp());
- }
- navDiv.addContent(navList);
- Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header));
- navDiv.addContent(aboutDiv);
- if (header) {
- fixedNavDiv.addContent(navDiv);
- } else {
- tree.addContent(navDiv);
- }
- Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious());
- ulNav.addContent(getNavLinkNext());
- Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav);
- Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists());
- ulFrames.addContent(getNavHideLists(filename));
- subDiv.addContent(ulFrames);
- HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
- ulAllClasses.addAttr(HtmlAttr.ID, allClassesId.toString());
- subDiv.addContent(ulAllClasses);
- if (header && configuration.createindex) {
- HtmlTree inputText = HtmlTree.INPUT("text", "search");
- HtmlTree inputReset = HtmlTree.INPUT("reset", "reset");
- Content searchTxt = configuration.getResource("doclet.search");
- searchTxt.addContent(getSpace());
- HtmlTree liInput = HtmlTree.LI(HtmlTree.SPAN(searchTxt));
- liInput.addContent(inputText);
- liInput.addContent(inputReset);
- HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput);
- subDiv.addContent(ulSearch);
- }
- subDiv.addContent(getAllClassesLinkScript(allClassesId.toString()));
- addSummaryDetailLinks(subDiv);
- if (header) {
- subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_TOP));
- fixedNavDiv.addContent(subDiv);
- fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
- tree.addContent(fixedNavDiv);
- } else {
- subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
- tree.addContent(subDiv);
- tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
- }
- if (configuration.allowTag(HtmlTag.NAV)) {
- htmlTree.addContent(tree);
- }
- }
- }
-
- /**
- * Get the word "NEXT" to indicate that no link is available. Override
- * this method to customize next link.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkNext() {
- return getNavLinkNext(null);
- }
-
- /**
- * Get the word "PREV" to indicate that no link is available. Override
- * this method to customize prev link.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkPrevious() {
- return getNavLinkPrevious(null);
- }
-
- /**
- * Do nothing. This is the default method.
- */
- protected void addSummaryDetailLinks(Content navDiv) {
- }
-
- /**
- * Get link to the "overview-summary.html" page.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkContents() {
- Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_SUMMARY),
- overviewLabel, "", "");
- Content li = HtmlTree.LI(linkContent);
- return li;
- }
-
- /**
- * Get link to the "package-summary.html" page for the package passed.
- *
- * @param pkg Package to which link will be generated
- * @return a content tree for the link
- */
- protected Content getNavLinkPackage(PackageDoc pkg) {
- Content linkContent = getPackageLink(pkg,
- packageLabel);
- Content li = HtmlTree.LI(linkContent);
- return li;
- }
-
- /**
- * Get the word "Package" , to indicate that link is not available here.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkPackage() {
- Content li = HtmlTree.LI(packageLabel);
- return li;
- }
-
- /**
- * Get the word "Use", to indicate that link is not available.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkClassUse() {
- Content li = HtmlTree.LI(useLabel);
- return li;
- }
-
- /**
- * Get link for previous file.
- *
- * @param prev File name for the prev link
- * @return a content tree for the link
- */
- public Content getNavLinkPrevious(DocPath prev) {
- Content li;
- if (prev != null) {
- li = HtmlTree.LI(getHyperLink(prev, prevLabel, "", ""));
- }
- else
- li = HtmlTree.LI(prevLabel);
- return li;
- }
-
- /**
- * Get link for next file. If next is null, just print the label
- * without linking it anywhere.
- *
- * @param next File name for the next link
- * @return a content tree for the link
- */
- public Content getNavLinkNext(DocPath next) {
- Content li;
- if (next != null) {
- li = HtmlTree.LI(getHyperLink(next, nextLabel, "", ""));
- }
- else
- li = HtmlTree.LI(nextLabel);
- return li;
- }
-
- /**
- * Get "FRAMES" link, to switch to the frame version of the output.
- *
- * @param link File to be linked, "index.html"
- * @return a content tree for the link
- */
- protected Content getNavShowLists(DocPath link) {
- DocLink dl = new DocLink(link, path.getPath(), null);
- Content framesContent = getHyperLink(dl, framesLabel, "", "_top");
- Content li = HtmlTree.LI(framesContent);
- return li;
- }
-
- /**
- * Get "FRAMES" link, to switch to the frame version of the output.
- *
- * @return a content tree for the link
- */
- protected Content getNavShowLists() {
- return getNavShowLists(pathToRoot.resolve(DocPaths.INDEX));
- }
-
- /**
- * Get "NO FRAMES" link, to switch to the non-frame version of the output.
- *
- * @param link File to be linked
- * @return a content tree for the link
- */
- protected Content getNavHideLists(DocPath link) {
- Content noFramesContent = getHyperLink(link, noframesLabel, "", "_top");
- Content li = HtmlTree.LI(noFramesContent);
- return li;
- }
-
- /**
- * Get "Tree" link in the navigation bar. If there is only one package
- * specified on the command line, then the "Tree" link will be to the
- * only "package-tree.html" file otherwise it will be to the
- * "overview-tree.html" file.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkTree() {
- Content treeLinkContent;
- PackageDoc[] packages = configuration.root.specifiedPackages();
- if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) {
- treeLinkContent = getHyperLink(pathString(packages[0],
- DocPaths.PACKAGE_TREE), treeLabel,
- "", "");
- } else {
- treeLinkContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
- treeLabel, "", "");
- }
- Content li = HtmlTree.LI(treeLinkContent);
- return li;
- }
-
- /**
- * Get the overview tree link for the main tree.
- *
- * @param label the label for the link
- * @return a content tree for the link
- */
- protected Content getNavLinkMainTree(String label) {
- Content mainTreeContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
- new StringContent(label));
- Content li = HtmlTree.LI(mainTreeContent);
- return li;
- }
-
- /**
- * Get the word "Class", to indicate that class link is not available.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkClass() {
- Content li = HtmlTree.LI(classLabel);
- return li;
- }
-
- /**
- * Get "Deprecated" API link in the navigation bar.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkDeprecated() {
- Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
- deprecatedLabel, "", "");
- Content li = HtmlTree.LI(linkContent);
- return li;
- }
-
- /**
- * Get link for generated index. If the user has used "-splitindex"
- * command line option, then link to file "index-files/index-1.html" is
- * generated otherwise link to file "index-all.html" is generated.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkClassIndex() {
- Content allClassesContent = getHyperLink(pathToRoot.resolve(
- DocPaths.ALLCLASSES_NOFRAME),
- allclassesLabel, "", "");
- Content li = HtmlTree.LI(allClassesContent);
- return li;
- }
-
- /**
- * Get link for generated class index.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkIndex() {
- Content linkContent = getHyperLink(pathToRoot.resolve(
- (configuration.splitindex
- ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1))
- : DocPaths.INDEX_ALL)),
- indexLabel, "", "");
- Content li = HtmlTree.LI(linkContent);
- return li;
- }
-
- /**
- * Get help file link. If user has provided a help file, then generate a
- * link to the user given file, which is already copied to current or
- * destination directory.
- *
- * @return a content tree for the link
- */
- protected Content getNavLinkHelp() {
- String helpfile = configuration.helpfile;
- DocPath helpfilenm;
- if (helpfile.isEmpty()) {
- helpfilenm = DocPaths.HELP_DOC;
- } else {
- DocFile file = DocFile.createFileForInput(configuration, helpfile);
- helpfilenm = DocPath.create(file.getName());
- }
- Content linkContent = getHyperLink(pathToRoot.resolve(helpfilenm),
- helpLabel, "", "");
- Content li = HtmlTree.LI(linkContent);
- return li;
- }
-
- /**
- * Get summary table header.
- *
- * @param header the header for the table
- * @param scope the scope of the headers
- * @return a content tree for the header
- */
- public Content getSummaryTableHeader(String[] header, String scope) {
- Content tr = new HtmlTree(HtmlTag.TR);
- int size = header.length;
- Content tableHeader;
- if (size == 1) {
- tableHeader = new StringContent(header[0]);
- tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader));
- return tr;
- }
- for (int i = 0; i < size; i++) {
- tableHeader = new StringContent(header[i]);
- if(i == 0)
- tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
- else if(i == (size - 1))
- tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
- else
- tr.addContent(HtmlTree.TH(scope, tableHeader));
- }
- return tr;
- }
-
- /**
- * Get table caption.
- *
- * @param rawText the caption for the table which could be raw Html
- * @return a content tree for the caption
- */
- public Content getTableCaption(Content title) {
- Content captionSpan = HtmlTree.SPAN(title);
- Content space = getSpace();
- Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
- Content caption = HtmlTree.CAPTION(captionSpan);
- caption.addContent(tabSpan);
- return caption;
- }
-
- /**
- * Get the marker anchor which will be added to the documentation tree.
- *
- * @param anchorName the anchor name attribute
- * @return a content tree for the marker anchor
- */
- public Content getMarkerAnchor(String anchorName) {
- return getMarkerAnchor(getName(anchorName), null);
- }
-
- /**
- * Get the marker anchor which will be added to the documentation tree.
- *
- * @param sectionName the section name anchor attribute for page
- * @return a content tree for the marker anchor
- */
- public Content getMarkerAnchor(SectionName sectionName) {
- return getMarkerAnchor(sectionName.getName(), null);
- }
-
- /**
- * Get the marker anchor which will be added to the documentation tree.
- *
- * @param sectionName the section name anchor attribute for page
- * @param anchorName the anchor name combined with section name attribute for the page
- * @return a content tree for the marker anchor
- */
- public Content getMarkerAnchor(SectionName sectionName, String anchorName) {
- return getMarkerAnchor(sectionName.getName() + getName(anchorName), null);
- }
-
- /**
- * Get the marker anchor which will be added to the documentation tree.
- *
- * @param anchorName the anchor name or id attribute
- * @param anchorContent the content that should be added to the anchor
- * @return a content tree for the marker anchor
- */
- public Content getMarkerAnchor(String anchorName, Content anchorContent) {
- if (anchorContent == null)
- anchorContent = new Comment(" ");
- Content markerAnchor = HtmlTree.A(configuration.htmlVersion, anchorName, anchorContent);
- return markerAnchor;
- }
-
- /**
- * Returns a packagename content.
- *
- * @param packageDoc the package to check
- * @return package name content
- */
- public Content getPackageName(PackageDoc packageDoc) {
- return packageDoc == null || packageDoc.name().isEmpty() ?
- defaultPackageLabel :
- getPackageLabel(packageDoc.name());
- }
-
- /**
- * Returns a package name label.
- *
- * @param packageName the package name
- * @return the package name content
- */
- public Content getPackageLabel(String packageName) {
- return new StringContent(packageName);
- }
-
- /**
- * Add package deprecation information to the documentation tree
- *
- * @param deprPkgs list of deprecated packages
- * @param headingKey the caption for the deprecated package table
- * @param tableSummary the summary for the deprecated package table
- * @param tableHeader table headers for the deprecated package table
- * @param contentTree the content tree to which the deprecated package table will be added
- */
- protected void addPackageDeprecatedAPI(List
- * Here is the algorithm used to fix the link:
- *
- * {@literal
- * For example, suppose com.sun.javadoc.RootDoc has this link:
- * {@literal The package Page }
- *
- * If this link appeared in the index, we would redirect
- * the link like this:
- *
- * {@literal The package Page}
- *
- * @param doc the Doc object whose documentation is being written.
- * @param text the text being written.
- *
- * @return the text, with all the relative links redirected to work.
- */
- private String redirectRelativeLinks(Doc doc, String text) {
- if (doc == null || shouldNotRedirectRelativeLinks()) {
- return text;
- }
-
- DocPath redirectPathFromRoot;
- if (doc instanceof ClassDoc) {
- redirectPathFromRoot = DocPath.forPackage(((ClassDoc) doc).containingPackage());
- } else if (doc instanceof MemberDoc) {
- redirectPathFromRoot = DocPath.forPackage(((MemberDoc) doc).containingPackage());
- } else if (doc instanceof PackageDoc) {
- redirectPathFromRoot = DocPath.forPackage((PackageDoc) doc);
- } else {
- return text;
- }
-
- //Redirect all relative links.
- int end, begin = StringUtils.indexOfIgnoreCase(text, "= 0){
- StringBuilder textBuff = new StringBuilder(text);
-
- while(begin >=0){
- if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
- begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), "", begin +1);
- if(begin == 0){
- //Link has no equal symbol.
- configuration.root.printWarning(
- doc.position(),
- configuration.getText("doclet.malformed_html_link_tag", text));
- break;
- }
- if (end == -1) {
- //Break without warning. This tag is not necessarily malformed. The text
- //might be missing '>' character because the href has an inline tag.
- break;
- }
-
- String quote = textBuff.substring(begin, end);
- quote = quote.contains("\"") ? "\"" :
- quote.contains("\'") ? "\'" : null;
- if (quote != null) {
- begin = textBuff.indexOf(quote, begin) + 1;
- end = textBuff.indexOf(quote, begin +1);
- if (begin == 0 || end == -1){
- //Link is missing a quote.
- break;
- }
- }
- String relativeLink = textBuff.substring(begin, end);
- String relativeLinkLowerCase = StringUtils.toLowerCase(relativeLink);
- if (!(relativeLinkLowerCase.startsWith("mailto:") ||
- relativeLinkLowerCase.startsWith("http:") ||
- relativeLinkLowerCase.startsWith("https:") ||
- relativeLinkLowerCase.startsWith("file:"))) {
- relativeLink = "{@"+(new DocRootTaglet()).getName() + "}/"
- + redirectPathFromRoot.resolve(relativeLink).getPath();
- textBuff.replace(begin, end, relativeLink);
- }
- begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), " blockTags = new HashSet<>();
- static {
- for (HtmlTag t: HtmlTag.values()) {
- if (t.blockType == HtmlTag.BlockType.BLOCK)
- blockTags.add(t.value);
- }
- }
-
- public static String removeNonInlineHtmlTags(String text) {
- final int len = text.length();
-
- int startPos = 0; // start of text to copy
- int lessThanPos = text.indexOf('<'); // position of latest '<'
- if (lessThanPos < 0) {
- return text;
- }
-
- StringBuilder result = new StringBuilder();
- main: while (lessThanPos != -1) {
- int currPos = lessThanPos + 1;
- if (currPos == len)
- break;
- char ch = text.charAt(currPos);
- if (ch == '/') {
- if (++currPos == len)
- break;
- ch = text.charAt(currPos);
- }
- int tagPos = currPos;
- while (isHtmlTagLetterOrDigit(ch)) {
- if (++currPos == len)
- break main;
- ch = text.charAt(currPos);
- }
- if (ch == '>' && blockTags.contains(StringUtils.toLowerCase(text.substring(tagPos, currPos)))) {
- result.append(text, startPos, lessThanPos);
- startPos = currPos + 1;
- }
- lessThanPos = text.indexOf('<', currPos);
- }
- result.append(text.substring(startPos));
-
- return result.toString();
- }
-
- private static boolean isHtmlTagLetterOrDigit(char ch) {
- return ('a' <= ch && ch <= 'z') ||
- ('A' <= ch && ch <= 'Z') ||
- ('1' <= ch && ch <= '6');
- }
-
- /**
- * Add a link to the stylesheet file.
- *
- * @param head the content tree to which the files will be added
- */
- public void addStyleSheetProperties(Content head) {
- String stylesheetfile = configuration.stylesheetfile;
- DocPath stylesheet;
- if (stylesheetfile.isEmpty()) {
- stylesheet = DocPaths.STYLESHEET;
- } else {
- DocFile file = DocFile.createFileForInput(configuration, stylesheetfile);
- stylesheet = DocPath.create(file.getName());
- }
- HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
- pathToRoot.resolve(stylesheet).getPath(),
- "Style");
- head.addContent(link);
- if (configuration.createindex) {
- HtmlTree jq_link = HtmlTree.LINK("stylesheet", "text/css",
- pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(DocPaths.JQUERY_STYLESHEET_FILE)).getPath(),
- "Style");
- head.addContent(jq_link);
- }
- }
-
- /**
- * Add a link to the JavaScript file.
- *
- * @param head the content tree to which the files will be added
- */
- public void addScriptProperties(Content head) {
- HtmlTree javascript = HtmlTree.SCRIPT(pathToRoot.resolve(DocPaths.JAVASCRIPT).getPath());
- head.addContent(javascript);
- if (configuration.createindex) {
- if (pathToRoot != null && script != null) {
- String path = pathToRoot.isEmpty() ? "." : pathToRoot.getPath();
- script.addContent(new RawHtml("var pathtoroot = \"" + path + "/\";loadScripts(document, \'script\');"));
- }
- addJQueryFile(head, DocPaths.JSZIP_MIN);
- addJQueryFile(head, DocPaths.JSZIPUTILS_MIN);
- head.addContent(new RawHtml(""));
- addJQueryFile(head, DocPaths.JQUERY_JS_1_10);
- addJQueryFile(head, DocPaths.JQUERY_JS);
- }
- }
-
- /**
- * Add a link to the JQuery javascript file.
- *
- * @param head the content tree to which the files will be added
- * @param filePath the DocPath of the file that needs to be added
- */
- private void addJQueryFile(Content head, DocPath filePath) {
- HtmlTree jqyeryScriptFile = HtmlTree.SCRIPT(
- pathToRoot.resolve(DocPaths.JQUERY_FILES.resolve(filePath)).getPath());
- head.addContent(jqyeryScriptFile);
- }
-
- /**
- * According to
- * The Java™ Language Specification,
- * all the outer classes and static nested classes are core classes.
- */
- public boolean isCoreClass(ClassDoc cd) {
- return cd.containingClass() == null || cd.isStatic();
- }
-
- /**
- * Adds the annotatation types for the given packageDoc.
- *
- * @param packageDoc the package to write annotations for.
- * @param htmltree the documentation tree to which the annotation info will be
- * added
- */
- public void addAnnotationInfo(PackageDoc packageDoc, Content htmltree) {
- addAnnotationInfo(packageDoc, packageDoc.annotations(), htmltree);
- }
-
- /**
- * Add the annotation types of the executable receiver.
- *
- * @param method the executable to write the receiver annotations for.
- * @param descList list of annotation description.
- * @param htmltree the documentation tree to which the annotation info will be
- * added
- */
- public void addReceiverAnnotationInfo(ExecutableMemberDoc method, AnnotationDesc[] descList,
- Content htmltree) {
- addAnnotationInfo(0, method, descList, false, htmltree);
- }
-
- /**
- * Adds the annotatation types for the given doc.
- *
- * @param doc the package to write annotations for
- * @param htmltree the content tree to which the annotation types will be added
- */
- public void addAnnotationInfo(ProgramElementDoc doc, Content htmltree) {
- addAnnotationInfo(doc, doc.annotations(), htmltree);
- }
-
- /**
- * Add the annotatation types for the given doc and parameter.
- *
- * @param indent the number of spaces to indent the parameters.
- * @param doc the doc to write annotations for.
- * @param param the parameter to write annotations for.
- * @param tree the content tree to which the annotation types will be added
- */
- public boolean addAnnotationInfo(int indent, Doc doc, Parameter param,
- Content tree) {
- return addAnnotationInfo(indent, doc, param.annotations(), false, tree);
- }
-
- /**
- * Adds the annotatation types for the given doc.
- *
- * @param doc the doc to write annotations for.
- * @param descList the array of {@link AnnotationDesc}.
- * @param htmltree the documentation tree to which the annotation info will be
- * added
- */
- private void addAnnotationInfo(Doc doc, AnnotationDesc[] descList,
- Content htmltree) {
- addAnnotationInfo(0, doc, descList, true, htmltree);
- }
-
- /**
- * Adds the annotation types for the given doc.
- *
- * @param indent the number of extra spaces to indent the annotations.
- * @param doc the doc to write annotations for.
- * @param descList the array of {@link AnnotationDesc}.
- * @param htmltree the documentation tree to which the annotation info will be
- * added
- */
- private boolean addAnnotationInfo(int indent, Doc doc,
- AnnotationDesc[] descList, boolean lineBreak, Content htmltree) {
- List This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.
+ *
+ * @since 1.2
+ * @author Atul M Dambalkar
+ * @author Robert Field
+ * @author Bhavesh Patel (Modified)
+ */
+public class HtmlDocletWriter extends HtmlDocWriter {
+
+ /**
+ * Relative path from the file getting generated to the destination
+ * directory. For example, if the file getting generated is
+ * "java/lang/Object.html", then the path to the root is "../..".
+ * This string can be empty if the file getting generated is in
+ * the destination directory.
+ */
+ public final DocPath pathToRoot;
+
+ /**
+ * Platform-independent path from the current or the
+ * destination directory to the file getting generated.
+ * Used when creating the file.
+ */
+ public final DocPath path;
+
+ /**
+ * Name of the file getting generated. If the file getting generated is
+ * "java/lang/Object.html", then the filename is "Object.html".
+ */
+ public final DocPath filename;
+
+ /**
+ * The global configuration information for this run.
+ */
+ public final ConfigurationImpl configuration;
+
+ protected final Utils utils;
+
+ /**
+ * To check whether annotation heading is printed or not.
+ */
+ protected boolean printedAnnotationHeading = false;
+
+ /**
+ * To check whether annotation field heading is printed or not.
+ */
+ protected boolean printedAnnotationFieldHeading = false;
+
+ /**
+ * To check whether the repeated annotations is documented or not.
+ */
+ private boolean isAnnotationDocumented = false;
+
+ /**
+ * To check whether the container annotations is documented or not.
+ */
+ private boolean isContainerDocumented = false;
+
+ HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV);
+
+ /**
+ * Constructor to construct the HtmlStandardWriter object.
+ *
+ * @param path File to be generated.
+ */
+ public HtmlDocletWriter(ConfigurationImpl configuration, DocPath path)
+ throws IOException {
+ super(configuration, path);
+ this.configuration = configuration;
+ this.utils = configuration.utils;
+ this.path = path;
+ this.pathToRoot = path.parent().invert();
+ this.filename = path.basename();
+ }
+
+ /**
+ * Replace {@docRoot} tag used in options that accept HTML text, such
+ * as -header, -footer, -top and -bottom, and when converting a relative
+ * HREF where commentTagsToString inserts a {@docRoot} where one was
+ * missing. (Also see DocRootTaglet for {@docRoot} tags in doc
+ * comments.)
+ *
+ * Replace {@docRoot} tag in htmlstr with the relative path to the
+ * destination directory from the directory where the file is being
+ * written, looping to handle all such tags in htmlstr.
+ *
+ * For example, for "-d docs" and -header containing {@docRoot}, when
+ * the HTML page for source file p/C1.java is being generated, the
+ * {@docRoot} tag would be inserted into the header as "../",
+ * the relative path from docs/p/ to docs/ (the document root).
+ *
+ * Note: This doc comment was written with '@' representing '@'
+ * to prevent the inline tag from being interpreted.
+ */
+ public String replaceDocRootDir(String htmlstr) {
+ // Return if no inline tags exist
+ int index = htmlstr.indexOf("{@");
+ if (index < 0) {
+ return htmlstr;
+ }
+ Matcher docrootMatcher = docrootPattern.matcher(htmlstr);
+ if (!docrootMatcher.find()) {
+ return htmlstr;
+ }
+ StringBuilder buf = new StringBuilder();
+ int prevEnd = 0;
+ do {
+ int match = docrootMatcher.start();
+ // append htmlstr up to start of next {@docroot}
+ buf.append(htmlstr.substring(prevEnd, match));
+ prevEnd = docrootMatcher.end();
+ if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", prevEnd)) {
+ // Insert the absolute link if {@docRoot} is followed by "/..".
+ buf.append(configuration.docrootparent);
+ prevEnd += 3;
+ } else {
+ // Insert relative path where {@docRoot} was located
+ buf.append(pathToRoot.isEmpty() ? "." : pathToRoot.getPath());
+ }
+ // Append slash if next character is not a slash
+ if (prevEnd < htmlstr.length() && htmlstr.charAt(prevEnd) != '/') {
+ buf.append('/');
+ }
+ } while (docrootMatcher.find());
+ buf.append(htmlstr.substring(prevEnd));
+ return buf.toString();
+ }
+ //where:
+ // Note: {@docRoot} is not case sensitive when passed in w/command line option:
+ private static final Pattern docrootPattern =
+ Pattern.compile(Pattern.quote("{@docroot}"), Pattern.CASE_INSENSITIVE);
+
+ /**
+ * Get the script to show or hide the All classes link.
+ *
+ * @param id id of the element to show or hide
+ * @return a content tree for the script
+ */
+ public Content getAllClassesLinkScript(String id) {
+ HtmlTree script = HtmlTree.SCRIPT();
+ String scriptCode = "" + DocletConstants.NL;
+ Content scriptContent = new RawHtml(scriptCode);
+ script.addContent(scriptContent);
+ Content div = HtmlTree.DIV(script);
+ Content div_noscript = HtmlTree.DIV(getResource("doclet.No_Script_Message"));
+ Content noScript = HtmlTree.NOSCRIPT(div_noscript);
+ div.addContent(noScript);
+ return div;
+ }
+
+ /**
+ * Add method information.
+ *
+ * @param method the method to be documented
+ * @param dl the content tree to which the method information will be added
+ */
+ private void addMethodInfo(ExecutableElement method, Content dl) {
+ TypeElement enclosing = utils.getEnclosingTypeElement(method);
+ List extends TypeMirror> intfacs = enclosing.getInterfaces();
+ ExecutableElement overriddenMethod = utils.overriddenMethod(method);
+ // Check whether there is any implementation or overridden info to be
+ // printed. If no overridden or implementation info needs to be
+ // printed, do not print this section.
+ if ((!intfacs.isEmpty()
+ && new ImplementedMethods(method, this.configuration).build().isEmpty() == false)
+ || overriddenMethod != null) {
+ MethodWriterImpl.addImplementsInfo(this, method, dl);
+ if (overriddenMethod != null) {
+ MethodWriterImpl.addOverridden(this,
+ utils.overriddenType(method),
+ overriddenMethod,
+ dl);
+ }
+ }
+ }
+
+ /**
+ * Adds the tags information.
+ *
+ * @param e the Element for which the tags will be generated
+ * @param htmltree the documentation tree to which the tags will be added
+ */
+ protected void addTagsInfo(Element e, Content htmltree) {
+ if (configuration.nocomment) {
+ return;
+ }
+ Content dl = new HtmlTree(HtmlTag.DL);
+ if (utils.isExecutableElement(e) && !utils.isConstructor(e)) {
+ addMethodInfo((ExecutableElement)e, dl);
+ }
+ Content output = new ContentBuilder();
+ TagletWriter.genTagOutput(configuration.tagletManager, e,
+ configuration.tagletManager.getCustomTaglets(e),
+ getTagletWriterInstance(false), output);
+ dl.addContent(output);
+ htmltree.addContent(dl);
+ }
+
+ /**
+ * Check whether there are any tags for Serialization Overview
+ * section to be printed.
+ *
+ * @param field the VariableElement object to check for tags.
+ * @return true if there are tags to be printed else return false.
+ */
+ protected boolean hasSerializationOverviewTags(VariableElement field) {
+ Content output = new ContentBuilder();
+ TagletWriter.genTagOutput(configuration.tagletManager, field,
+ configuration.tagletManager.getCustomTaglets(field),
+ getTagletWriterInstance(false), output);
+ return !output.isEmpty();
+ }
+
+ /**
+ * Returns a TagletWriter that knows how to write HTML.
+ *
+ * @return a TagletWriter that knows how to write HTML.
+ */
+ public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
+ return new TagletWriterImpl(this, isFirstSentence);
+ }
+
+ /**
+ * Get Package link, with target frame.
+ *
+ * @param pkg The link will be to the "package-summary.html" page for this package
+ * @param target name of the target frame
+ * @param label tag for the link
+ * @return a content for the target package link
+ */
+ public Content getTargetPackageLink(PackageElement pkg, String target,
+ Content label) {
+ return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
+ }
+
+
+ public void addClassesSummary(SortedSet
+ * Here is the algorithm used to fix the link:
+ *
+ * {@literal
+ * For example, suppose DocletEnvironment has this link:
+ * {@literal The package Page }
+ *
+ * If this link appeared in the index, we would redirect
+ * the link like this:
+ *
+ * {@literal The package Page}
+ *
+ * @param element the Element object whose documentation is being written.
+ * @param text the text being written.
+ *
+ * @return the text, with all the relative links redirected to work.
+ */
+ private String redirectRelativeLinks(Element element, TextTree tt) {
+ String text = tt.getBody();
+ if (element == null || utils.isOverviewElement(element) || shouldNotRedirectRelativeLinks()) {
+ return text;
+ }
+
+ DocPath redirectPathFromRoot = new SimpleElementVisitor9