duke@1: /* jjg@1326: * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.doclets.formats.html; duke@1: duke@1: import java.io.*; duke@1: import java.text.SimpleDateFormat; duke@1: import java.util.*; duke@1: bpatel@233: import com.sun.javadoc.*; bpatel@233: import com.sun.tools.doclets.formats.html.markup.*; bpatel@233: import com.sun.tools.doclets.internal.toolkit.*; bpatel@233: import com.sun.tools.doclets.internal.toolkit.util.*; bpatel@233: import com.sun.tools.doclets.internal.toolkit.taglets.*; duke@1: duke@1: /** duke@1: * Class for the Html Format Code Generation specific to JavaDoc. duke@1: * This Class contains methods related to the Html Code Generation which duke@1: * are used extensively while generating the entire documentation. duke@1: * duke@1: * @since 1.2 duke@1: * @author Atul M Dambalkar duke@1: * @author Robert Field bpatel@233: * @author Bhavesh Patel (Modified) duke@1: */ duke@1: public class HtmlDocletWriter extends HtmlDocWriter { duke@1: duke@1: /** duke@1: * Relative path from the file getting generated to the destination duke@1: * directory. For example, if the file getting generated is duke@1: * "java/lang/Object.html", then the relative path string is "../../". duke@1: * This string can be empty if the file getting generated is in duke@1: * the destination directory. duke@1: */ duke@1: public String relativePath = ""; duke@1: duke@1: /** duke@1: * Same as relativepath, but normalized to never be empty or duke@1: * end with a slash. duke@1: */ duke@1: public String relativepathNoSlash = ""; duke@1: duke@1: /** duke@1: * Platform-dependent directory path from the current or the duke@1: * destination directory to the file getting generated. duke@1: * Used when creating the file. duke@1: * For example, if the file getting generated is duke@1: * "java/lang/Object.html", then the path string is "java/lang". duke@1: */ duke@1: public String path = ""; duke@1: duke@1: /** duke@1: * Name of the file getting generated. If the file getting generated is duke@1: * "java/lang/Object.html", then the filename is "Object.html". duke@1: */ duke@1: public String filename = ""; duke@1: duke@1: /** duke@1: * The display length used for indentation while generating the class page. duke@1: */ duke@1: public int displayLength = 0; duke@1: duke@1: /** duke@1: * The global configuration information for this run. duke@1: */ duke@1: public ConfigurationImpl configuration; duke@1: duke@1: /** bpatel@766: * To check whether annotation heading is printed or not. bpatel@766: */ bpatel@766: protected boolean printedAnnotationHeading = false; bpatel@766: bpatel@766: /** duke@1: * Constructor to construct the HtmlStandardWriter object. duke@1: * duke@1: * @param filename File to be generated. duke@1: */ duke@1: public HtmlDocletWriter(ConfigurationImpl configuration, duke@1: String filename) throws IOException { duke@1: super(configuration, filename); duke@1: this.configuration = configuration; duke@1: this.filename = filename; duke@1: } duke@1: duke@1: /** duke@1: * Constructor to construct the HtmlStandardWriter object. duke@1: * duke@1: * @param path Platform-dependent {@link #path} used when duke@1: * creating file. duke@1: * @param filename Name of file to be generated. duke@1: * @param relativePath Value for the variable {@link #relativePath}. duke@1: */ duke@1: public HtmlDocletWriter(ConfigurationImpl configuration, duke@1: String path, String filename, duke@1: String relativePath) throws IOException { duke@1: super(configuration, path, filename); duke@1: this.configuration = configuration; duke@1: this.path = path; duke@1: this.relativePath = relativePath; duke@1: this.relativepathNoSlash = duke@1: DirectoryManager.getPathNoTrailingSlash(this.relativePath); duke@1: this.filename = filename; duke@1: } duke@1: duke@1: /** duke@1: * Replace {@docRoot} tag used in options that accept HTML text, such duke@1: * as -header, -footer, -top and -bottom, and when converting a relative duke@1: * HREF where commentTagsToString inserts a {@docRoot} where one was duke@1: * missing. (Also see DocRootTaglet for {@docRoot} tags in doc duke@1: * comments.) duke@1: *
duke@1: * Replace {@docRoot} tag in htmlstr with the relative path to the duke@1: * destination directory from the directory where the file is being duke@1: * written, looping to handle all such tags in htmlstr. duke@1: *
duke@1: * For example, for "-d docs" and -header containing {@docRoot}, when duke@1: * the HTML page for source file p/C1.java is being generated, the duke@1: * {@docRoot} tag would be inserted into the header as "../", duke@1: * the relative path from docs/p/ to docs/ (the document root). duke@1: *
duke@1: * Note: This doc comment was written with '@' representing '@' duke@1: * to prevent the inline tag from being interpreted. duke@1: */ duke@1: public String replaceDocRootDir(String htmlstr) { duke@1: // Return if no inline tags exist duke@1: int index = htmlstr.indexOf("{@"); duke@1: if (index < 0) { duke@1: return htmlstr; duke@1: } duke@1: String lowerHtml = htmlstr.toLowerCase(); duke@1: // Return index of first occurrence of {@docroot} duke@1: // Note: {@docRoot} is not case sensitive when passed in w/command line option duke@1: index = lowerHtml.indexOf("{@docroot}", index); duke@1: if (index < 0) { duke@1: return htmlstr; duke@1: } jjg@910: StringBuilder buf = new StringBuilder(); duke@1: int previndex = 0; duke@1: while (true) { bpatel@997: if (configuration.docrootparent.length() > 0) { bpatel@997: // Search for lowercase version of {@docRoot}/.. bpatel@997: index = lowerHtml.indexOf("{@docroot}/..", previndex); bpatel@997: // If next {@docRoot}/.. pattern not found, append rest of htmlstr and exit loop bpatel@997: if (index < 0) { bpatel@997: buf.append(htmlstr.substring(previndex)); bpatel@997: break; bpatel@997: } bpatel@997: // If next {@docroot}/.. pattern found, append htmlstr up to start of tag bpatel@997: buf.append(htmlstr.substring(previndex, index)); bpatel@997: previndex = index + 13; // length for {@docroot}/.. string bpatel@997: // Insert docrootparent absolute path where {@docRoot}/.. was located bpatel@997: bpatel@997: buf.append(configuration.docrootparent); bpatel@997: // Append slash if next character is not a slash bpatel@997: if (previndex < htmlstr.length() && htmlstr.charAt(previndex) != '/') { bpatel@997: buf.append(DirectoryManager.URL_FILE_SEPARATOR); bpatel@997: } bpatel@997: } else { bpatel@997: // Search for lowercase version of {@docRoot} bpatel@997: index = lowerHtml.indexOf("{@docroot}", previndex); bpatel@997: // If next {@docRoot} tag not found, append rest of htmlstr and exit loop bpatel@997: if (index < 0) { bpatel@997: buf.append(htmlstr.substring(previndex)); bpatel@997: break; bpatel@997: } bpatel@997: // If next {@docroot} tag found, append htmlstr up to start of tag bpatel@997: buf.append(htmlstr.substring(previndex, index)); bpatel@997: previndex = index + 10; // length for {@docroot} string bpatel@997: // Insert relative path where {@docRoot} was located bpatel@997: buf.append(relativepathNoSlash); bpatel@997: // Append slash if next character is not a slash bpatel@997: if (relativepathNoSlash.length() > 0 && previndex < htmlstr.length() && bpatel@997: htmlstr.charAt(previndex) != '/') { bpatel@997: buf.append(DirectoryManager.URL_FILE_SEPARATOR); bpatel@997: } duke@1: } duke@1: } duke@1: return buf.toString(); duke@1: } duke@1: duke@1: /** duke@1: * Print Html Hyper Link, with target frame. This duke@1: * link will only appear if page is not in a frame. duke@1: * duke@1: * @param link String name of the file. duke@1: * @param where Position in the file duke@1: * @param target Name of the target frame. duke@1: * @param label Tag for the link. bpatel@182: * @param strong Whether the label should be strong or not? duke@1: */ duke@1: public void printNoFramesTargetHyperLink(String link, String where, duke@1: String target, String label, bpatel@182: boolean strong) { duke@1: script(); duke@1: println(" "); duke@1: scriptEnd(); duke@1: noScript(); bpatel@766: println(" " + getHyperLinkString(link, where, label, strong, "", "", target)); duke@1: noScriptEnd(); duke@1: println(DocletConstants.NL); duke@1: } duke@1: bpatel@766: /** bpatel@766: * Get the script to show or hide the All classes link. bpatel@766: * bpatel@766: * @param id id of the element to show or hide bpatel@766: * @return a content tree for the script bpatel@766: */ bpatel@766: public Content getAllClassesLinkScript(String id) { bpatel@766: HtmlTree script = new HtmlTree(HtmlTag.SCRIPT); bpatel@766: script.addAttr(HtmlAttr.TYPE, "text/javascript"); bpatel@793: String scriptCode = "" + DocletConstants.NL; bpatel@766: Content scriptContent = new RawHtml(scriptCode); bpatel@766: script.addContent(scriptContent); bpatel@766: Content div = HtmlTree.DIV(script); bpatel@766: return div; bpatel@766: } bpatel@766: bpatel@766: /** bpatel@766: * Add method information. bpatel@766: * bpatel@766: * @param method the method to be documented bpatel@766: * @param dl the content tree to which the method information will be added bpatel@766: */ bpatel@766: private void addMethodInfo(MethodDoc method, Content dl) { duke@1: ClassDoc[] intfacs = method.containingClass().interfaces(); duke@1: MethodDoc overriddenMethod = method.overriddenMethod(); bpatel@233: // Check whether there is any implementation or overridden info to be bpatel@233: // printed. If no overridden or implementation info needs to be bpatel@233: // printed, do not print this section. bpatel@233: if ((intfacs.length > 0 && bpatel@233: new ImplementedMethods(method, this.configuration).build().length > 0) || bpatel@233: overriddenMethod != null) { bpatel@766: MethodWriterImpl.addImplementsInfo(this, method, dl); duke@1: if (overriddenMethod != null) { bpatel@766: MethodWriterImpl.addOverridden(this, bpatel@766: method.overriddenType(), overriddenMethod, dl); duke@1: } duke@1: } duke@1: } duke@1: bpatel@766: /** bpatel@766: * Adds the tags information. bpatel@766: * bpatel@766: * @param doc the doc for which the tags will be generated bpatel@766: * @param htmltree the documentation tree to which the tags will be added bpatel@766: */ bpatel@766: protected void addTagsInfo(Doc doc, Content htmltree) { bpatel@766: if (configuration.nocomment) { duke@1: return; duke@1: } bpatel@766: Content dl = new HtmlTree(HtmlTag.DL); duke@1: if (doc instanceof MethodDoc) { bpatel@766: addMethodInfo((MethodDoc) doc, dl); duke@1: } duke@1: TagletOutputImpl output = new TagletOutputImpl(""); duke@1: TagletWriter.genTagOuput(configuration.tagletManager, doc, duke@1: configuration.tagletManager.getCustomTags(doc), duke@1: getTagletWriterInstance(false), output); bpatel@233: String outputString = output.toString().trim(); bpatel@233: if (!outputString.isEmpty()) { bpatel@766: Content resultString = new RawHtml(outputString); bpatel@766: dl.addContent(resultString); duke@1: } bpatel@766: htmltree.addContent(dl); duke@1: } duke@1: duke@1: /** bpatel@233: * Check whether there are any tags for Serialization Overview bpatel@233: * section to be printed. bpatel@222: * bpatel@233: * @param field the FieldDoc object to check for tags. bpatel@222: * @return true if there are tags to be printed else return false. bpatel@222: */ bpatel@233: protected boolean hasSerializationOverviewTags(FieldDoc field) { bpatel@222: TagletOutputImpl output = new TagletOutputImpl(""); bpatel@233: TagletWriter.genTagOuput(configuration.tagletManager, field, bpatel@233: configuration.tagletManager.getCustomTags(field), bpatel@222: getTagletWriterInstance(false), output); bpatel@233: return (!output.toString().trim().isEmpty()); bpatel@222: } bpatel@222: bpatel@222: /** duke@1: * Returns a TagletWriter that knows how to write HTML. duke@1: * duke@1: * @return a TagletWriter that knows how to write HTML. duke@1: */ duke@1: public TagletWriter getTagletWriterInstance(boolean isFirstSentence) { duke@1: return new TagletWriterImpl(this, isFirstSentence); duke@1: } duke@1: duke@1: protected void printTagsInfoHeader() { duke@1: dl(); duke@1: } duke@1: duke@1: protected void printTagsInfoFooter() { duke@1: dlEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get Package link, with target frame. duke@1: * bpatel@766: * @param pd The link will be to the "package-summary.html" page for this package bpatel@766: * @param target name of the target frame bpatel@766: * @param label tag for the link bpatel@766: * @return a content for the target package link duke@1: */ bpatel@766: public Content getTargetPackageLink(PackageDoc pd, String target, bpatel@766: Content label) { bpatel@766: return getHyperLink(pathString(pd, "package-summary.html"), "", label, "", target); duke@1: } duke@1: duke@1: /** duke@1: * Print the html file header. Also print Html page title and stylesheet duke@1: * default properties. duke@1: * duke@1: * @param title String window title to go in the <TITLE> tag duke@1: * @param metakeywords Array of String keywords for META tag. Each element duke@1: * of the array is assigned to a separate META tag. duke@1: * Pass in null for no array. duke@1: * @param includeScript boolean true if printing windowtitle script. duke@1: * False for files that appear in the left-hand frames. duke@1: */ duke@1: public void printHtmlHeader(String title, String[] metakeywords, duke@1: boolean includeScript) { duke@1: println(""); duke@1: println(""); duke@1: html(); duke@1: head(); duke@1: if (! configuration.notimestamp) { duke@1: print(""); duke@1: } duke@1: if (configuration.charset.length() > 0) { duke@1: println(""); duke@1: } duke@1: if ( configuration.windowtitle.length() > 0 ) { duke@1: title += " (" + configuration.windowtitle + ")"; duke@1: } duke@1: title(title); duke@1: println(title); duke@1: titleEnd(); duke@1: println(""); duke@1: if (! configuration.notimestamp) { duke@1: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); duke@1: println(""); duke@1: } duke@1: if ( metakeywords != null ) { duke@1: for ( int i=0; i < metakeywords.length; i++ ) { duke@1: println(""); duke@1: } duke@1: } duke@1: println(""); duke@1: printStyleSheetProperties(); duke@1: println(""); duke@1: // Don't print windowtitle script for overview-frame, allclasses-frame duke@1: // and package-frame duke@1: if (includeScript) { duke@1: printWinTitleScript(title); duke@1: } duke@1: println(""); duke@1: headEnd(); duke@1: println(""); duke@1: body("white", includeScript); duke@1: } duke@1: duke@1: /** bpatel@766: * Generates the HTML document tree and prints it out. bpatel@766: * bpatel@766: * @param metakeywords Array of String keywords for META tag. Each element bpatel@766: * of the array is assigned to a separate META tag. bpatel@766: * Pass in null for no array bpatel@766: * @param includeScript true if printing windowtitle script bpatel@766: * false for files that appear in the left-hand frames bpatel@766: * @param body the body htmltree to be included in the document bpatel@766: */ bpatel@766: public void printHtmlDocument(String[] metakeywords, boolean includeScript, bpatel@766: Content body) { bpatel@766: Content htmlDocType = DocType.Transitional(); bpatel@766: Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); bpatel@766: Content head = new HtmlTree(HtmlTag.HEAD); bpatel@766: if (!configuration.notimestamp) { bpatel@766: Content headComment = new Comment("Generated by javadoc (version " + bpatel@766: ConfigurationImpl.BUILD_DATE + ") on " + today()); bpatel@766: head.addContent(headComment); bpatel@766: } bpatel@766: if (configuration.charset.length() > 0) { bpatel@766: Content meta = HtmlTree.META("Content-Type", "text/html", bpatel@766: configuration.charset); bpatel@766: head.addContent(meta); bpatel@766: } bpatel@766: head.addContent(getTitle()); bpatel@766: if (!configuration.notimestamp) { bpatel@766: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); bpatel@766: Content meta = HtmlTree.META("date", dateFormat.format(new Date())); bpatel@766: head.addContent(meta); bpatel@766: } bpatel@766: if (metakeywords != null) { bpatel@766: for (int i=0; i < metakeywords.length; i++) { bpatel@766: Content meta = HtmlTree.META("keywords", metakeywords[i]); bpatel@766: head.addContent(meta); bpatel@766: } bpatel@766: } bpatel@766: head.addContent(getStyleSheetProperties()); bpatel@766: Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), bpatel@766: head, body); bpatel@766: Content htmlDocument = new HtmlDocument(htmlDocType, bpatel@766: htmlComment, htmlTree); bpatel@766: print(htmlDocument.toString()); bpatel@766: } bpatel@766: bpatel@766: /** bpatel@766: * Get the window title. bpatel@766: * bpatel@766: * @param title the title string to construct the complete window title bpatel@766: * @return the window title string bpatel@766: */ bpatel@766: public String getWindowTitle(String title) { bpatel@766: if (configuration.windowtitle.length() > 0) { bpatel@766: title += " (" + configuration.windowtitle + ")"; bpatel@766: } bpatel@766: return title; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print user specified header and the footer. duke@1: * duke@1: * @param header if true print the user provided header else print the duke@1: * user provided footer. duke@1: */ duke@1: public void printUserHeaderFooter(boolean header) { duke@1: em(); duke@1: if (header) { duke@1: print(replaceDocRootDir(configuration.header)); duke@1: } else { duke@1: if (configuration.footer.length() != 0) { duke@1: print(replaceDocRootDir(configuration.footer)); duke@1: } else { duke@1: print(replaceDocRootDir(configuration.header)); duke@1: } duke@1: } duke@1: emEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get user specified header and the footer. bpatel@766: * bpatel@766: * @param header if true print the user provided header else print the bpatel@766: * user provided footer. bpatel@766: */ bpatel@766: public Content getUserHeaderFooter(boolean header) { bpatel@766: String content; bpatel@766: if (header) { bpatel@766: content = replaceDocRootDir(configuration.header); bpatel@766: } else { bpatel@766: if (configuration.footer.length() != 0) { bpatel@766: content = replaceDocRootDir(configuration.footer); bpatel@766: } else { bpatel@766: content = replaceDocRootDir(configuration.header); bpatel@766: } bpatel@766: } bpatel@766: Content rawContent = new RawHtml(content); bpatel@766: Content em = HtmlTree.EM(rawContent); bpatel@766: return em; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the user specified top. duke@1: */ duke@1: public void printTop() { duke@1: print(replaceDocRootDir(configuration.top)); duke@1: hr(); duke@1: } duke@1: duke@1: /** bpatel@766: * Adds the user specified top. bpatel@766: * bpatel@766: * @param body the content tree to which user specified top will be added bpatel@766: */ bpatel@766: public void addTop(Content body) { bpatel@766: Content top = new RawHtml(replaceDocRootDir(configuration.top)); bpatel@766: body.addContent(top); bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the user specified bottom. duke@1: */ duke@1: public void printBottom() { duke@1: hr(); duke@1: print(replaceDocRootDir(configuration.bottom)); duke@1: } duke@1: duke@1: /** bpatel@766: * Adds the user specified bottom. bpatel@766: * bpatel@766: * @param body the content tree to which user specified bottom will be added bpatel@766: */ bpatel@766: public void addBottom(Content body) { bpatel@766: Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom)); bpatel@766: Content small = HtmlTree.SMALL(bottom); bpatel@766: Content p = HtmlTree.P(HtmlStyle.legalCopy, small); bpatel@766: body.addContent(p); bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the navigation bar for the Html page at the top and and the bottom. duke@1: * duke@1: * @param header If true print navigation bar at the top of the page else duke@1: * print the nevigation bar at the bottom. duke@1: */ duke@1: protected void navLinks(boolean header) { duke@1: println(""); duke@1: if (!configuration.nonavbar) { duke@1: if (header) { duke@1: println(DocletConstants.NL + ""); duke@1: anchor("navbar_top"); duke@1: println(); bpatel@766: print(getHyperLinkString("", "skip-navbar_top", "", false, "", duke@1: configuration.getText("doclet.Skip_navigation_links"), "")); duke@1: } else { duke@1: println(DocletConstants.NL + ""); duke@1: anchor("navbar_bottom"); duke@1: println(); bpatel@766: print(getHyperLinkString("", "skip-navbar_bottom", "", false, "", duke@1: configuration.getText("doclet.Skip_navigation_links"), "")); duke@1: } duke@1: table(0, "100%", 1, 0); duke@1: tr(); duke@1: tdColspanBgcolorStyle(2, "#EEEEFF", "NavBarCell1"); duke@1: println(""); duke@1: if (header) { duke@1: anchor("navbar_top_firstrow"); duke@1: } else { duke@1: anchor("navbar_bottom_firstrow"); duke@1: } duke@1: table(0, 0, 3); duke@1: print(" "); duke@1: trAlignVAlign("center", "top"); duke@1: duke@1: if (configuration.createoverview) { duke@1: navLinkContents(); duke@1: } duke@1: duke@1: if (configuration.packages.length == 1) { duke@1: navLinkPackage(configuration.packages[0]); duke@1: } else if (configuration.packages.length > 1) { duke@1: navLinkPackage(); duke@1: } duke@1: duke@1: navLinkClass(); duke@1: duke@1: if(configuration.classuse) { duke@1: navLinkClassUse(); duke@1: } duke@1: if(configuration.createtree) { duke@1: navLinkTree(); duke@1: } duke@1: if(!(configuration.nodeprecated || duke@1: configuration.nodeprecatedlist)) { duke@1: navLinkDeprecated(); duke@1: } duke@1: if(configuration.createindex) { duke@1: navLinkIndex(); duke@1: } duke@1: if (!configuration.nohelp) { duke@1: navLinkHelp(); duke@1: } duke@1: print(" "); duke@1: trEnd(); duke@1: tableEnd(); duke@1: tdEnd(); duke@1: duke@1: tdAlignVAlignRowspan("right", "top", 3); duke@1: duke@1: printUserHeaderFooter(header); duke@1: tdEnd(); duke@1: trEnd(); duke@1: println(""); duke@1: duke@1: tr(); duke@1: tdBgcolorStyle("white", "NavBarCell2"); duke@1: font("-2"); duke@1: space(); duke@1: navLinkPrevious(); duke@1: space(); duke@1: println(""); duke@1: space(); duke@1: navLinkNext(); duke@1: fontEnd(); duke@1: tdEnd(); duke@1: duke@1: tdBgcolorStyle("white", "NavBarCell2"); duke@1: font("-2"); duke@1: print(" "); duke@1: navShowLists(); duke@1: print(" "); duke@1: space(); duke@1: println(""); duke@1: space(); duke@1: navHideLists(filename); duke@1: print(" "); duke@1: space(); duke@1: println(""); duke@1: space(); duke@1: navLinkClassIndex(); duke@1: fontEnd(); duke@1: tdEnd(); duke@1: duke@1: trEnd(); duke@1: duke@1: printSummaryDetailLinks(); duke@1: duke@1: tableEnd(); duke@1: if (header) { duke@1: aName("skip-navbar_top"); duke@1: aEnd(); duke@1: println(DocletConstants.NL + ""); duke@1: } else { duke@1: aName("skip-navbar_bottom"); duke@1: aEnd(); duke@1: println(DocletConstants.NL + ""); duke@1: } duke@1: println(""); duke@1: } duke@1: } duke@1: duke@1: /** bpatel@766: * Adds the navigation bar for the Html page at the top and and the bottom. bpatel@766: * bpatel@766: * @param header If true print navigation bar at the top of the page else bpatel@766: * @param body the HtmlTree to which the nav links will be added bpatel@766: */ bpatel@766: protected void addNavLinks(boolean header, Content body) { bpatel@766: if (!configuration.nonavbar) { bpatel@766: String allClassesId = "allclasses_"; bpatel@766: HtmlTree navDiv = new HtmlTree(HtmlTag.DIV); bpatel@766: if (header) { bpatel@766: body.addContent(HtmlConstants.START_OF_TOP_NAVBAR); bpatel@766: navDiv.addStyle(HtmlStyle.topNav); bpatel@766: allClassesId += "navbar_top"; bpatel@766: Content a = getMarkerAnchor("navbar_top"); bpatel@766: navDiv.addContent(a); bpatel@766: Content skipLinkContent = getHyperLink("", bpatel@766: "skip-navbar_top", HtmlTree.EMPTY, configuration.getText( bpatel@766: "doclet.Skip_navigation_links"), ""); bpatel@766: navDiv.addContent(skipLinkContent); bpatel@766: } else { bpatel@766: body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR); bpatel@766: navDiv.addStyle(HtmlStyle.bottomNav); bpatel@766: allClassesId += "navbar_bottom"; bpatel@766: Content a = getMarkerAnchor("navbar_bottom"); bpatel@766: navDiv.addContent(a); bpatel@766: Content skipLinkContent = getHyperLink("", bpatel@766: "skip-navbar_bottom", HtmlTree.EMPTY, configuration.getText( bpatel@766: "doclet.Skip_navigation_links"), ""); bpatel@766: navDiv.addContent(skipLinkContent); bpatel@766: } bpatel@766: if (header) { bpatel@766: navDiv.addContent(getMarkerAnchor("navbar_top_firstrow")); bpatel@766: } else { bpatel@766: navDiv.addContent(getMarkerAnchor("navbar_bottom_firstrow")); bpatel@766: } bpatel@766: HtmlTree navList = new HtmlTree(HtmlTag.UL); bpatel@766: navList.addStyle(HtmlStyle.navList); bpatel@766: navList.addAttr(HtmlAttr.TITLE, "Navigation"); bpatel@766: if (configuration.createoverview) { bpatel@766: navList.addContent(getNavLinkContents()); bpatel@766: } bpatel@766: if (configuration.packages.length == 1) { bpatel@766: navList.addContent(getNavLinkPackage(configuration.packages[0])); bpatel@766: } else if (configuration.packages.length > 1) { bpatel@766: navList.addContent(getNavLinkPackage()); bpatel@766: } bpatel@766: navList.addContent(getNavLinkClass()); bpatel@766: if(configuration.classuse) { bpatel@766: navList.addContent(getNavLinkClassUse()); bpatel@766: } bpatel@766: if(configuration.createtree) { bpatel@766: navList.addContent(getNavLinkTree()); bpatel@766: } bpatel@766: if(!(configuration.nodeprecated || bpatel@766: configuration.nodeprecatedlist)) { bpatel@766: navList.addContent(getNavLinkDeprecated()); bpatel@766: } bpatel@766: if(configuration.createindex) { bpatel@766: navList.addContent(getNavLinkIndex()); bpatel@766: } bpatel@766: if (!configuration.nohelp) { bpatel@766: navList.addContent(getNavLinkHelp()); bpatel@766: } bpatel@766: navDiv.addContent(navList); bpatel@766: Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header)); bpatel@766: navDiv.addContent(aboutDiv); bpatel@766: body.addContent(navDiv); bpatel@766: Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious()); bpatel@766: ulNav.addContent(getNavLinkNext()); bpatel@766: Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav); bpatel@766: Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists()); bpatel@766: ulFrames.addContent(getNavHideLists(filename)); bpatel@766: subDiv.addContent(ulFrames); bpatel@766: HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex()); bpatel@766: ulAllClasses.addAttr(HtmlAttr.ID, allClassesId.toString()); bpatel@766: subDiv.addContent(ulAllClasses); bpatel@766: subDiv.addContent(getAllClassesLinkScript(allClassesId.toString())); bpatel@766: addSummaryDetailLinks(subDiv); bpatel@766: if (header) { bpatel@766: subDiv.addContent(getMarkerAnchor("skip-navbar_top")); bpatel@766: body.addContent(subDiv); bpatel@766: body.addContent(HtmlConstants.END_OF_TOP_NAVBAR); bpatel@766: } else { bpatel@766: subDiv.addContent(getMarkerAnchor("skip-navbar_bottom")); bpatel@766: body.addContent(subDiv); bpatel@766: body.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR); bpatel@766: } bpatel@766: } bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the word "NEXT" to indicate that no link is available. Override duke@1: * this method to customize next link. duke@1: */ duke@1: protected void navLinkNext() { duke@1: navLinkNext(null); duke@1: } duke@1: duke@1: /** bpatel@766: * Get the word "NEXT" to indicate that no link is available. Override bpatel@766: * this method to customize next link. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkNext() { bpatel@766: return getNavLinkNext(null); bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the word "PREV" to indicate that no link is available. Override duke@1: * this method to customize prev link. duke@1: */ duke@1: protected void navLinkPrevious() { duke@1: navLinkPrevious(null); duke@1: } duke@1: duke@1: /** bpatel@766: * Get the word "PREV" to indicate that no link is available. Override bpatel@766: * this method to customize prev link. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkPrevious() { bpatel@766: return getNavLinkPrevious(null); bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Do nothing. This is the default method. duke@1: */ duke@1: protected void printSummaryDetailLinks() { duke@1: } duke@1: duke@1: /** bpatel@766: * Do nothing. This is the default method. bpatel@766: */ bpatel@766: protected void addSummaryDetailLinks(Content navDiv) { bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print link to the "overview-summary.html" page. duke@1: */ duke@1: protected void navLinkContents() { duke@1: navCellStart(); duke@1: printHyperLink(relativePath + "overview-summary.html", "", duke@1: configuration.getText("doclet.Overview"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get link to the "overview-summary.html" page. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkContents() { bpatel@766: Content linkContent = getHyperLink(relativePath + bpatel@766: "overview-summary.html", "", overviewLabel, "", ""); bpatel@766: Content li = HtmlTree.LI(linkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Description for a cell in the navigation bar. duke@1: */ duke@1: protected void navCellStart() { duke@1: print(" "); duke@1: tdBgcolorStyle("#EEEEFF", "NavBarCell1"); duke@1: print(" "); duke@1: } duke@1: duke@1: /** duke@1: * Description for a cell in the navigation bar, but with reverse duke@1: * high-light effect. duke@1: */ duke@1: protected void navCellRevStart() { duke@1: print(" "); duke@1: tdBgcolorStyle("#FFFFFF", "NavBarCell1Rev"); duke@1: print(" "); duke@1: space(); duke@1: } duke@1: duke@1: /** duke@1: * Closing tag for navigation bar cell. duke@1: */ duke@1: protected void navCellEnd() { duke@1: space(); duke@1: tdEnd(); duke@1: } duke@1: duke@1: /** duke@1: * Print link to the "package-summary.html" page for the package passed. duke@1: * duke@1: * @param pkg Package to which link will be generated. duke@1: */ duke@1: protected void navLinkPackage(PackageDoc pkg) { duke@1: navCellStart(); duke@1: printPackageLink(pkg, configuration.getText("doclet.Package"), true, duke@1: "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get link to the "package-summary.html" page for the package passed. bpatel@766: * bpatel@766: * @param pkg Package to which link will be generated bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkPackage(PackageDoc pkg) { bpatel@766: Content linkContent = getPackageLink(pkg, bpatel@766: packageLabel); bpatel@766: Content li = HtmlTree.LI(linkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the word "Package" in the navigation bar cell, to indicate that duke@1: * link is not available here. duke@1: */ duke@1: protected void navLinkPackage() { duke@1: navCellStart(); duke@1: fontStyle("NavBarFont1"); duke@1: printText("doclet.Package"); duke@1: fontEnd(); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get the word "Package" , to indicate that link is not available here. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkPackage() { bpatel@766: Content li = HtmlTree.LI(packageLabel); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the word "Use" in the navigation bar cell, to indicate that link duke@1: * is not available. duke@1: */ duke@1: protected void navLinkClassUse() { duke@1: navCellStart(); duke@1: fontStyle("NavBarFont1"); duke@1: printText("doclet.navClassUse"); duke@1: fontEnd(); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get the word "Use", to indicate that link is not available. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkClassUse() { bpatel@766: Content li = HtmlTree.LI(useLabel); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print link for previous file. duke@1: * duke@1: * @param prev File name for the prev link. duke@1: */ duke@1: public void navLinkPrevious(String prev) { duke@1: String tag = configuration.getText("doclet.Prev"); duke@1: if (prev != null) { duke@1: printHyperLink(prev, "", tag, true) ; duke@1: } else { duke@1: print(tag); duke@1: } duke@1: } duke@1: duke@1: /** bpatel@766: * Get link for previous file. bpatel@766: * bpatel@766: * @param prev File name for the prev link bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: public Content getNavLinkPrevious(String prev) { bpatel@766: Content li; bpatel@766: if (prev != null) { bpatel@766: li = HtmlTree.LI(getHyperLink(prev, "", prevLabel, "", "")); bpatel@766: } bpatel@766: else bpatel@766: li = HtmlTree.LI(prevLabel); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print link for next file. If next is null, just print the label duke@1: * without linking it anywhere. duke@1: * duke@1: * @param next File name for the next link. duke@1: */ duke@1: public void navLinkNext(String next) { duke@1: String tag = configuration.getText("doclet.Next"); duke@1: if (next != null) { duke@1: printHyperLink(next, "", tag, true); duke@1: } else { duke@1: print(tag); duke@1: } duke@1: } duke@1: duke@1: /** bpatel@766: * Get link for next file. If next is null, just print the label bpatel@766: * without linking it anywhere. bpatel@766: * bpatel@766: * @param next File name for the next link bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: public Content getNavLinkNext(String next) { bpatel@766: Content li; bpatel@766: if (next != null) { bpatel@766: li = HtmlTree.LI(getHyperLink(next, "", nextLabel, "", "")); bpatel@766: } bpatel@766: else bpatel@766: li = HtmlTree.LI(nextLabel); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print "FRAMES" link, to switch to the frame version of the output. duke@1: * duke@1: * @param link File to be linked, "index.html". duke@1: */ duke@1: protected void navShowLists(String link) { bpatel@766: print(getHyperLinkString(link + "?" + path + filename, "", duke@1: configuration.getText("doclet.FRAMES"), true, "", "", "_top")); duke@1: } duke@1: duke@1: /** bpatel@766: * Get "FRAMES" link, to switch to the frame version of the output. bpatel@766: * bpatel@766: * @param link File to be linked, "index.html" bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavShowLists(String link) { bpatel@766: Content framesContent = getHyperLink(link + "?" + path + bpatel@766: filename, "", framesLabel, "", "_top"); bpatel@766: Content li = HtmlTree.LI(framesContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print "FRAMES" link, to switch to the frame version of the output. duke@1: */ duke@1: protected void navShowLists() { duke@1: navShowLists(relativePath + "index.html"); duke@1: } duke@1: duke@1: /** bpatel@766: * Get "FRAMES" link, to switch to the frame version of the output. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavShowLists() { bpatel@766: return getNavShowLists(relativePath + "index.html"); bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print "NO FRAMES" link, to switch to the non-frame version of the output. duke@1: * duke@1: * @param link File to be linked. duke@1: */ duke@1: protected void navHideLists(String link) { bpatel@766: print(getHyperLinkString(link, "", configuration.getText("doclet.NO_FRAMES"), duke@1: true, "", "", "_top")); duke@1: } duke@1: duke@1: /** bpatel@766: * Get "NO FRAMES" link, to switch to the non-frame version of the output. bpatel@766: * bpatel@766: * @param link File to be linked bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavHideLists(String link) { bpatel@766: Content noFramesContent = getHyperLink(link, "", noframesLabel, "", "_top"); bpatel@766: Content li = HtmlTree.LI(noFramesContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print "Tree" link in the navigation bar. If there is only one package duke@1: * specified on the command line, then the "Tree" link will be to the duke@1: * only "package-tree.html" file otherwise it will be to the duke@1: * "overview-tree.html" file. duke@1: */ duke@1: protected void navLinkTree() { duke@1: navCellStart(); duke@1: PackageDoc[] packages = configuration.root.specifiedPackages(); duke@1: if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) { duke@1: printHyperLink(pathString(packages[0], "package-tree.html"), "", duke@1: configuration.getText("doclet.Tree"), true, "NavBarFont1"); duke@1: } else { duke@1: printHyperLink(relativePath + "overview-tree.html", "", duke@1: configuration.getText("doclet.Tree"), true, "NavBarFont1"); duke@1: } duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get "Tree" link in the navigation bar. If there is only one package bpatel@766: * specified on the command line, then the "Tree" link will be to the bpatel@766: * only "package-tree.html" file otherwise it will be to the bpatel@766: * "overview-tree.html" file. bpatel@766: * bpatel@766: * @return a content tree for the link duke@1: */ bpatel@766: protected Content getNavLinkTree() { bpatel@766: Content treeLinkContent; bpatel@766: PackageDoc[] packages = configuration.root.specifiedPackages(); bpatel@766: if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) { bpatel@766: treeLinkContent = getHyperLink(pathString(packages[0], bpatel@766: "package-tree.html"), "", treeLabel, bpatel@766: "", ""); bpatel@766: } else { bpatel@766: treeLinkContent = getHyperLink(relativePath + "overview-tree.html", bpatel@766: "", treeLabel, "", ""); bpatel@766: } bpatel@766: Content li = HtmlTree.LI(treeLinkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** bpatel@766: * Get the overview tree link for the main tree. bpatel@766: * bpatel@766: * @param label the label for the link bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkMainTree(String label) { bpatel@766: Content mainTreeContent = getHyperLink(relativePath + "overview-tree.html", bpatel@766: new StringContent(label)); bpatel@766: Content li = HtmlTree.LI(mainTreeContent); bpatel@766: return li; duke@1: } duke@1: duke@1: /** duke@1: * Print the word "Class" in the navigation bar cell, to indicate that duke@1: * class link is not available. duke@1: */ duke@1: protected void navLinkClass() { duke@1: navCellStart(); duke@1: fontStyle("NavBarFont1"); duke@1: printText("doclet.Class"); duke@1: fontEnd(); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get the word "Class", to indicate that class link is not available. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkClass() { bpatel@766: Content li = HtmlTree.LI(classLabel); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print "Deprecated" API link in the navigation bar. duke@1: */ duke@1: protected void navLinkDeprecated() { duke@1: navCellStart(); duke@1: printHyperLink(relativePath + "deprecated-list.html", "", duke@1: configuration.getText("doclet.navDeprecated"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get "Deprecated" API link in the navigation bar. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkDeprecated() { bpatel@766: Content linkContent = getHyperLink(relativePath + bpatel@766: "deprecated-list.html", "", deprecatedLabel, "", ""); bpatel@766: Content li = HtmlTree.LI(linkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print link for generated index. If the user has used "-splitindex" duke@1: * command line option, then link to file "index-files/index-1.html" is duke@1: * generated otherwise link to file "index-all.html" is generated. duke@1: */ duke@1: protected void navLinkClassIndex() { duke@1: printNoFramesTargetHyperLink(relativePath + duke@1: AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, duke@1: "", "", configuration.getText("doclet.All_Classes"), true); duke@1: } bpatel@766: bpatel@766: /** bpatel@766: * Get link for generated index. If the user has used "-splitindex" bpatel@766: * command line option, then link to file "index-files/index-1.html" is bpatel@766: * generated otherwise link to file "index-all.html" is generated. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkClassIndex() { bpatel@766: Content allClassesContent = getHyperLink(relativePath + bpatel@766: AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, "", bpatel@766: allclassesLabel, "", ""); bpatel@766: Content li = HtmlTree.LI(allClassesContent); bpatel@766: return li; bpatel@766: } duke@1: /** duke@1: * Print link for generated class index. duke@1: */ duke@1: protected void navLinkIndex() { duke@1: navCellStart(); duke@1: printHyperLink(relativePath + duke@1: (configuration.splitindex? duke@1: DirectoryManager.getPath("index-files") + duke@1: fileseparator: "") + duke@1: (configuration.splitindex? duke@1: "index-1.html" : "index-all.html"), "", duke@1: configuration.getText("doclet.Index"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get link for generated class index. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkIndex() { bpatel@766: Content linkContent = getHyperLink(relativePath +(configuration.splitindex? bpatel@766: DirectoryManager.getPath("index-files") + fileseparator: "") + bpatel@766: (configuration.splitindex?"index-1.html" : "index-all.html"), "", bpatel@766: indexLabel, "", ""); bpatel@766: Content li = HtmlTree.LI(linkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print help file link. If user has provided a help file, then generate a duke@1: * link to the user given file, which is already copied to current or duke@1: * destination directory. duke@1: */ duke@1: protected void navLinkHelp() { duke@1: String helpfilenm = configuration.helpfile; duke@1: if (helpfilenm.equals("")) { duke@1: helpfilenm = "help-doc.html"; duke@1: } else { duke@1: int lastsep; duke@1: if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) { duke@1: helpfilenm = helpfilenm.substring(lastsep + 1); duke@1: } duke@1: } duke@1: navCellStart(); duke@1: printHyperLink(relativePath + helpfilenm, "", duke@1: configuration.getText("doclet.Help"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** bpatel@766: * Get help file link. If user has provided a help file, then generate a bpatel@766: * link to the user given file, which is already copied to current or bpatel@766: * destination directory. bpatel@766: * bpatel@766: * @return a content tree for the link bpatel@766: */ bpatel@766: protected Content getNavLinkHelp() { bpatel@766: String helpfilenm = configuration.helpfile; bpatel@766: if (helpfilenm.equals("")) { bpatel@766: helpfilenm = "help-doc.html"; bpatel@766: } else { bpatel@766: int lastsep; bpatel@766: if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) { bpatel@766: helpfilenm = helpfilenm.substring(lastsep + 1); bpatel@766: } bpatel@766: } bpatel@766: Content linkContent = getHyperLink(relativePath + helpfilenm, "", bpatel@766: helpLabel, "", ""); bpatel@766: Content li = HtmlTree.LI(linkContent); bpatel@766: return li; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Print the word "Detail" in the navigation bar. No link is available. duke@1: */ duke@1: protected void navDetail() { duke@1: printText("doclet.Detail"); duke@1: } duke@1: duke@1: /** duke@1: * Print the word "Summary" in the navigation bar. No link is available. duke@1: */ duke@1: protected void navSummary() { duke@1: printText("doclet.Summary"); duke@1: } duke@1: duke@1: /** duke@1: * Print the Html table tag for the index summary tables. The table tag duke@1: * printed is jjg@1326: * {@code
");
duke@1: }
duke@1:
duke@1: /**
bpatel@243: * Print table caption.
bpatel@243: */
bpatel@243: public void tableCaptionStart() {
bpatel@243: captionStyle("TableCaption");
bpatel@243: }
bpatel@243:
bpatel@243: /**
bpatel@243: * Print table sub-caption.
bpatel@243: */
bpatel@243: public void tableSubCaptionStart() {
bpatel@243: captionStyle("TableSubCaption");
bpatel@243: }
bpatel@243:
bpatel@243: /**
bpatel@243: * Print table caption end tags.
bpatel@243: */
bpatel@243: public void tableCaptionEnd() {
bpatel@243: captionEnd();
bpatel@243: }
bpatel@243:
bpatel@243: /**
bpatel@243: * Print summary table header.
bpatel@243: */
bpatel@243: public void summaryTableHeader(String[] header, String scope) {
bpatel@243: tr();
bpatel@243: for ( int i=0; i < header.length; i++ ) {
bpatel@243: thScopeNoWrap("TableHeader", scope);
bpatel@243: print(header[i]);
bpatel@243: thEnd();
bpatel@243: }
bpatel@243: trEnd();
bpatel@243: }
bpatel@243:
bpatel@243: /**
bpatel@766: * Get summary table header.
bpatel@766: *
bpatel@766: * @param header the header for the table
bpatel@766: * @param scope the scope of the headers
bpatel@766: * @return a content tree for the header
bpatel@766: */
bpatel@766: public Content getSummaryTableHeader(String[] header, String scope) {
bpatel@766: Content tr = new HtmlTree(HtmlTag.TR);
bpatel@766: int size = header.length;
bpatel@766: Content tableHeader;
bpatel@766: if (size == 1) {
bpatel@766: tableHeader = new StringContent(header[0]);
bpatel@766: tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader));
bpatel@766: return tr;
bpatel@766: }
bpatel@766: for (int i = 0; i < size; i++) {
bpatel@766: tableHeader = new StringContent(header[i]);
bpatel@766: if(i == 0)
bpatel@766: tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
bpatel@766: else if(i == (size - 1))
bpatel@766: tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
bpatel@766: else
bpatel@766: tr.addContent(HtmlTree.TH(scope, tableHeader));
bpatel@766: }
bpatel@766: return tr;
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Get table caption.
bpatel@766: *
bpatel@766: * @param rawText the caption for the table which could be raw Html
bpatel@766: * @return a content tree for the caption
bpatel@766: */
bpatel@766: public Content getTableCaption(String rawText) {
bpatel@766: Content title = new RawHtml(rawText);
bpatel@766: Content captionSpan = HtmlTree.SPAN(title);
bpatel@766: Content space = getSpace();
bpatel@766: Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
bpatel@766: Content caption = HtmlTree.CAPTION(captionSpan);
bpatel@766: caption.addContent(tabSpan);
bpatel@766: return caption;
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Get the marker anchor which will be added to the documentation tree.
bpatel@766: *
bpatel@766: * @param anchorName the anchor name attribute
bpatel@766: * @return a content tree for the marker anchor
bpatel@766: */
bpatel@766: public Content getMarkerAnchor(String anchorName) {
bpatel@766: return getMarkerAnchor(anchorName, null);
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Get the marker anchor which will be added to the documentation tree.
bpatel@766: *
bpatel@766: * @param anchorName the anchor name attribute
bpatel@766: * @param anchorContent the content that should be added to the anchor
bpatel@766: * @return a content tree for the marker anchor
bpatel@766: */
bpatel@766: public Content getMarkerAnchor(String anchorName, Content anchorContent) {
bpatel@766: if (anchorContent == null)
bpatel@766: anchorContent = new Comment(" ");
bpatel@766: Content markerAnchor = HtmlTree.A_NAME(anchorName, anchorContent);
bpatel@766: return markerAnchor;
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Returns a packagename content.
bpatel@766: *
bpatel@766: * @param packageDoc the package to check
bpatel@766: * @return package name content
bpatel@766: */
bpatel@766: public Content getPackageName(PackageDoc packageDoc) {
bpatel@766: return packageDoc == null || packageDoc.name().length() == 0 ?
bpatel@766: defaultPackageLabel :
bpatel@766: getPackageLabel(packageDoc.name());
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Returns a package name label.
bpatel@766: *
bpatel@766: * @param parsedName the package name
bpatel@766: * @return the package name content
bpatel@766: */
bpatel@766: public Content getPackageLabel(String packageName) {
bpatel@766: return new StringContent(packageName);
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@995: * Add package deprecation information to the documentation tree
bpatel@995: *
bpatel@995: * @param deprPkgs list of deprecated packages
bpatel@995: * @param headingKey the caption for the deprecated package table
bpatel@995: * @param tableSummary the summary for the deprecated package table
bpatel@995: * @param tableHeader table headers for the deprecated package table
bpatel@995: * @param contentTree the content tree to which the deprecated package table will be added
bpatel@995: */
bpatel@995: protected void addPackageDeprecatedAPI(List} format.
duke@1: *
duke@1: * @param str The Header string.
duke@1: */
duke@1: public void printIndexHeading(String str) {
duke@1: h2();
duke@1: print(str);
duke@1: h2End();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print Html tag <FRAMESET=arg>.
duke@1: *
duke@1: * @param arg Argument for the tag.
duke@1: */
duke@1: public void frameSet(String arg) {
duke@1: println("");
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print Html tag <FRAME=arg>.
duke@1: *
duke@1: * @param arg Argument for the tag.
duke@1: */
duke@1: public void frame(String arg) {
duke@1: println("");
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print Html closing tag </FRAME>.
duke@1: */
duke@1: public void frameEnd() {
duke@1: println("");
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return path to the class page for a classdoc. For example, the class
duke@1: * name is "java.lang.Object" and if the current file getting generated is
duke@1: * "java/io/File.html", then the path string to the class, returned is
duke@1: * "../../java/lang.Object.html".
duke@1: *
duke@1: * @param cd Class to which the path is requested.
duke@1: */
duke@1: protected String pathToClass(ClassDoc cd) {
duke@1: return pathString(cd.containingPackage(), cd.name() + ".html");
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the path to the class page for a classdoc. Works same as
duke@1: * {@link #pathToClass(ClassDoc)}.
duke@1: *
duke@1: * @param cd Class to which the path is requested.
duke@1: * @param name Name of the file(doesn't include path).
duke@1: */
duke@1: protected String pathString(ClassDoc cd, String name) {
duke@1: return pathString(cd.containingPackage(), name);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return path to the given file name in the given package. So if the name
duke@1: * passed is "Object.html" and the name of the package is "java.lang", and
duke@1: * if the relative path is "../.." then returned string will be
duke@1: * "../../java/lang/Object.html"
duke@1: *
duke@1: * @param pd Package in which the file name is assumed to be.
duke@1: * @param name File name, to which path string is.
duke@1: */
duke@1: protected String pathString(PackageDoc pd, String name) {
duke@1: StringBuffer buf = new StringBuffer(relativePath);
duke@1: buf.append(DirectoryManager.getPathToPackage(pd, name));
duke@1: return buf.toString();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print the link to the given package.
duke@1: *
duke@1: * @param pkg the package to link to.
duke@1: * @param label the label for the link.
bpatel@182: * @param isStrong true if the label should be strong.
duke@1: */
bpatel@182: public void printPackageLink(PackageDoc pkg, String label, boolean isStrong) {
bpatel@766: print(getPackageLinkString(pkg, label, isStrong));
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print the link to the given package.
duke@1: *
duke@1: * @param pkg the package to link to.
duke@1: * @param label the label for the link.
bpatel@182: * @param isStrong true if the label should be strong.
duke@1: * @param style the font of the package link label.
duke@1: */
bpatel@182: public void printPackageLink(PackageDoc pkg, String label, boolean isStrong,
duke@1: String style) {
bpatel@766: print(getPackageLinkString(pkg, label, isStrong, style));
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the link to the given package.
duke@1: *
duke@1: * @param pkg the package to link to.
duke@1: * @param label the label for the link.
bpatel@182: * @param isStrong true if the label should be strong.
duke@1: * @return the link to the given package.
duke@1: */
bpatel@766: public String getPackageLinkString(PackageDoc pkg, String label,
bpatel@182: boolean isStrong) {
bpatel@766: return getPackageLinkString(pkg, label, isStrong, "");
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the link to the given package.
duke@1: *
duke@1: * @param pkg the package to link to.
duke@1: * @param label the label for the link.
bpatel@182: * @param isStrong true if the label should be strong.
duke@1: * @param style the font of the package link label.
duke@1: * @return the link to the given package.
duke@1: */
bpatel@766: public String getPackageLinkString(PackageDoc pkg, String label, boolean isStrong,
duke@1: String style) {
duke@1: boolean included = pkg != null && pkg.isIncluded();
duke@1: if (! included) {
duke@1: PackageDoc[] packages = configuration.packages;
duke@1: for (int i = 0; i < packages.length; i++) {
duke@1: if (packages[i].equals(pkg)) {
duke@1: included = true;
duke@1: break;
duke@1: }
duke@1: }
duke@1: }
duke@1: if (included || pkg == null) {
bpatel@766: return getHyperLinkString(pathString(pkg, "package-summary.html"),
bpatel@182: "", label, isStrong, style);
duke@1: } else {
duke@1: String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
duke@1: if (crossPkgLink != null) {
bpatel@766: return getHyperLinkString(crossPkgLink, "", label, isStrong, style);
bpatel@766: } else {
bpatel@766: return label;
bpatel@766: }
bpatel@766: }
bpatel@766: }
bpatel@766:
bpatel@766: /**
bpatel@766: * Return the link to the given package.
bpatel@766: *
bpatel@766: * @param pkg the package to link to.
bpatel@766: * @param label the label for the link.
bpatel@766: * @return a content tree for the package link.
bpatel@766: */
bpatel@766: public Content getPackageLink(PackageDoc pkg, Content label) {
bpatel@766: boolean included = pkg != null && pkg.isIncluded();
bpatel@766: if (! included) {
bpatel@766: PackageDoc[] packages = configuration.packages;
bpatel@766: for (int i = 0; i < packages.length; i++) {
bpatel@766: if (packages[i].equals(pkg)) {
bpatel@766: included = true;
bpatel@766: break;
bpatel@766: }
bpatel@766: }
bpatel@766: }
bpatel@766: if (included || pkg == null) {
bpatel@766: return getHyperLink(pathString(pkg, "package-summary.html"),
bpatel@766: "", label);
bpatel@766: } else {
bpatel@766: String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
bpatel@766: if (crossPkgLink != null) {
bpatel@766: return getHyperLink(crossPkgLink, "", label);
duke@1: } else {
duke@1: return label;
duke@1: }
duke@1: }
duke@1: }
duke@1:
duke@1: public String italicsClassName(ClassDoc cd, boolean qual) {
duke@1: String name = (qual)? cd.qualifiedName(): cd.name();
duke@1: return (cd.isInterface())? italicsText(name): name;
duke@1: }
duke@1:
duke@1: public void printSrcLink(ProgramElementDoc d, String label) {
duke@1: if (d == null) {
duke@1: return;
duke@1: }
duke@1: ClassDoc cd = d.containingClass();
duke@1: if (cd == null) {
duke@1: //d must be a class doc since in has no containing class.
duke@1: cd = (ClassDoc) d;
duke@1: }
duke@1: String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
duke@1: + DirectoryManager.getDirectoryPath(cd.containingPackage())
duke@1: + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(d);
duke@1: printHyperLink(href, "", label, true);
duke@1: }
duke@1:
duke@1: /**
bpatel@766: * Add the link to the content tree.
bpatel@766: *
bpatel@766: * @param doc program element doc for which the link will be added
bpatel@766: * @param label label for the link
bpatel@766: * @param htmltree the content tree to which the link will be added
bpatel@766: */
bpatel@766: public void addSrcLink(ProgramElementDoc doc, Content label, Content htmltree) {
bpatel@766: if (doc == null) {
bpatel@766: return;
bpatel@766: }
bpatel@766: ClassDoc cd = doc.containingClass();
bpatel@766: if (cd == null) {
bpatel@766: //d must be a class doc since in has no containing class.
bpatel@766: cd = (ClassDoc) doc;
bpatel@766: }
bpatel@766: String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
bpatel@766: + DirectoryManager.getDirectoryPath(cd.containingPackage())
bpatel@766: + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(doc);
bpatel@766: Content linkContent = getHyperLink(href, "", label, "", "");
bpatel@766: htmltree.addContent(linkContent);
bpatel@766: }
bpatel@766:
bpatel@766: /**
duke@1: * Return the link to the given class.
duke@1: *
duke@1: * @param linkInfo the information about the link.
duke@1: *
duke@1: * @return the link for the given class.
duke@1: */
duke@1: public String getLink(LinkInfoImpl linkInfo) {
duke@1: LinkFactoryImpl factory = new LinkFactoryImpl(this);
duke@1: String link = ((LinkOutputImpl) factory.getLinkOutput(linkInfo)).toString();
duke@1: displayLength += linkInfo.displayLength;
duke@1: return link;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the type parameters for the given class.
duke@1: *
duke@1: * @param linkInfo the information about the link.
duke@1: * @return the type for the given class.
duke@1: */
duke@1: public String getTypeParameterLinks(LinkInfoImpl linkInfo) {
duke@1: LinkFactoryImpl factory = new LinkFactoryImpl(this);
duke@1: return ((LinkOutputImpl)
duke@1: factory.getTypeParameterLinks(linkInfo, false)).toString();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print the link to the given class.
duke@1: */
duke@1: public void printLink(LinkInfoImpl linkInfo) {
duke@1: print(getLink(linkInfo));
duke@1: }
duke@1:
duke@1: /*************************************************************
duke@1: * Return a class cross link to external class documentation.
duke@1: * The name must be fully qualified to determine which package
duke@1: * the class is in. The -link option does not allow users to
duke@1: * link to external classes in the "default" package.
duke@1: *
duke@1: * @param qualifiedClassName the qualified name of the external class.
duke@1: * @param refMemName the name of the member being referenced. This should
duke@1: * be null or empty string if no member is being referenced.
duke@1: * @param label the label for the external link.
bpatel@182: * @param strong true if the link should be strong.
duke@1: * @param style the style of the link.
duke@1: * @param code true if the label should be code font.
duke@1: */
duke@1: public String getCrossClassLink(String qualifiedClassName, String refMemName,
bpatel@182: String label, boolean strong, String style,
duke@1: boolean code) {
duke@1: String className = "",
duke@1: packageName = qualifiedClassName == null ? "" : qualifiedClassName;
duke@1: int periodIndex;
duke@1: while((periodIndex = packageName.lastIndexOf('.')) != -1) {
duke@1: className = packageName.substring(periodIndex + 1, packageName.length()) +
duke@1: (className.length() > 0 ? "." + className : "");
duke@1: String defaultLabel = code ? getCode() + className + getCodeEnd() : className;
duke@1: packageName = packageName.substring(0, periodIndex);
duke@1: if (getCrossPackageLink(packageName) != null) {
duke@1: //The package exists in external documentation, so link to the external
duke@1: //class (assuming that it exists). This is definitely a limitation of
duke@1: //the -link option. There are ways to determine if an external package
duke@1: //exists, but no way to determine if the external class exists. We just
duke@1: //have to assume that it does.
bpatel@766: return getHyperLinkString(
duke@1: configuration.extern.getExternalLink(packageName, relativePath,
duke@1: className + ".html?is-external=true"),
duke@1: refMemName == null ? "" : refMemName,
duke@1: label == null || label.length() == 0 ? defaultLabel : label,
bpatel@182: strong, style,
duke@1: configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
duke@1: "");
duke@1: }
duke@1: }
duke@1: return null;
duke@1: }
duke@1:
duke@1: public boolean isClassLinkable(ClassDoc cd) {
duke@1: if (cd.isIncluded()) {
duke@1: return configuration.isGeneratedDoc(cd);
duke@1: }
duke@1: return configuration.extern.isExternal(cd);
duke@1: }
duke@1:
duke@1: public String getCrossPackageLink(String pkgName) {
duke@1: return configuration.extern.getExternalLink(pkgName, relativePath,
duke@1: "package-summary.html?is-external=true");
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Get the class link.
bpatel@766: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param cd the class doc to link to
bpatel@766: * @return a content tree for the link
bpatel@766: */
bpatel@766: public Content getQualifiedClassLink(int context, ClassDoc cd) {
bpatel@766: return new RawHtml(getLink(new LinkInfoImpl(context, cd,
bpatel@766: configuration.getClassName(cd), "")));
duke@1: }
duke@1:
duke@1: /**
bpatel@766: * Add the class link.
bpatel@766: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param cd the class doc to link to
bpatel@766: * @param contentTree the content tree to which the link will be added
duke@1: */
bpatel@766: public void addPreQualifiedClassLink(int context, ClassDoc cd, Content contentTree) {
bpatel@766: addPreQualifiedClassLink(context, cd, false, contentTree);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Retrieve the class link with the package portion of the label in
duke@1: * plain text. If the qualifier is excluded, it willnot be included in the
duke@1: * link label.
duke@1: *
duke@1: * @param cd the class to link to.
bpatel@182: * @param isStrong true if the link should be strong.
duke@1: * @return the link with the package portion of the label in plain text.
duke@1: */
duke@1: public String getPreQualifiedClassLink(int context,
bpatel@182: ClassDoc cd, boolean isStrong) {
duke@1: String classlink = "";
duke@1: PackageDoc pd = cd.containingPackage();
duke@1: if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
duke@1: classlink = getPkgName(cd);
duke@1: }
bpatel@182: classlink += getLink(new LinkInfoImpl(context, cd, cd.name(), isStrong));
duke@1: return classlink;
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Add the class link with the package portion of the label in
bpatel@766: * plain text. If the qualifier is excluded, it will not be included in the
bpatel@766: * link label.
bpatel@766: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param cd the class to link to
bpatel@766: * @param isStrong true if the link should be strong
bpatel@766: * @param contentTree the content tree to which the link with be added
bpatel@766: */
bpatel@766: public void addPreQualifiedClassLink(int context,
bpatel@766: ClassDoc cd, boolean isStrong, Content contentTree) {
bpatel@766: PackageDoc pd = cd.containingPackage();
bpatel@766: if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
bpatel@766: contentTree.addContent(getPkgName(cd));
bpatel@766: }
bpatel@766: contentTree.addContent(new RawHtml(getLink(new LinkInfoImpl(
bpatel@766: context, cd, cd.name(), isStrong))));
bpatel@766: }
duke@1:
duke@1: /**
bpatel@766: * Add the class link, with only class name as the strong link and prefixing
duke@1: * plain package name.
bpatel@766: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param cd the class to link to
bpatel@766: * @param contentTree the content tree to which the link with be added
duke@1: */
bpatel@766: public void addPreQualifiedStrongClassLink(int context, ClassDoc cd, Content contentTree) {
bpatel@766: addPreQualifiedClassLink(context, cd, true, contentTree);
duke@1: }
duke@1:
duke@1: public void printText(String key) {
duke@1: print(configuration.getText(key));
duke@1: }
duke@1:
duke@1: public void printText(String key, String a1) {
duke@1: print(configuration.getText(key, a1));
duke@1: }
duke@1:
duke@1: public void printText(String key, String a1, String a2) {
duke@1: print(configuration.getText(key, a1, a2));
duke@1: }
duke@1:
bpatel@182: public void strongText(String key) {
bpatel@182: strong(configuration.getText(key));
duke@1: }
duke@1:
bpatel@182: public void strongText(String key, String a1) {
bpatel@182: strong(configuration.getText(key, a1));
duke@1: }
duke@1:
bpatel@182: public void strongText(String key, String a1, String a2) {
bpatel@182: strong(configuration.getText(key, a1, a2));
duke@1: }
duke@1:
duke@1: /**
bpatel@766: * Get the link for the given member.
duke@1: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param doc the member being linked to
bpatel@766: * @param label the label for the link
bpatel@766: * @return a content tree for the doc link
duke@1: */
bpatel@766: public Content getDocLink(int context, MemberDoc doc, String label) {
bpatel@766: return getDocLink(context, doc.containingClass(), doc, label);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Print the link for the given member.
duke@1: *
duke@1: * @param context the id of the context where the link will be printed.
duke@1: * @param classDoc the classDoc that we should link to. This is not
duke@1: * necessarily equal to doc.containingClass(). We may be
duke@1: * inheriting comments.
duke@1: * @param doc the member being linked to.
duke@1: * @param label the label for the link.
bpatel@182: * @param strong true if the link should be strong.
duke@1: */
duke@1: public void printDocLink(int context, ClassDoc classDoc, MemberDoc doc,
bpatel@182: String label, boolean strong) {
bpatel@182: print(getDocLink(context, classDoc, doc, label, strong));
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the link for the given member.
duke@1: *
duke@1: * @param context the id of the context where the link will be printed.
duke@1: * @param doc the member being linked to.
duke@1: * @param label the label for the link.
bpatel@182: * @param strong true if the link should be strong.
duke@1: * @return the link for the given member.
duke@1: */
duke@1: public String getDocLink(int context, MemberDoc doc, String label,
bpatel@182: boolean strong) {
bpatel@182: return getDocLink(context, doc.containingClass(), doc, label, strong);
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return the link for the given member.
duke@1: *
duke@1: * @param context the id of the context where the link will be printed.
duke@1: * @param classDoc the classDoc that we should link to. This is not
duke@1: * necessarily equal to doc.containingClass(). We may be
duke@1: * inheriting comments.
duke@1: * @param doc the member being linked to.
duke@1: * @param label the label for the link.
bpatel@182: * @param strong true if the link should be strong.
duke@1: * @return the link for the given member.
duke@1: */
duke@1: public String getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
bpatel@182: String label, boolean strong) {
duke@1: if (! (doc.isIncluded() ||
duke@1: Util.isLinkable(classDoc, configuration()))) {
duke@1: return label;
duke@1: } else if (doc instanceof ExecutableMemberDoc) {
duke@1: ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
duke@1: return getLink(new LinkInfoImpl(context, classDoc,
bpatel@182: getAnchor(emd), label, strong));
duke@1: } else if (doc instanceof MemberDoc) {
duke@1: return getLink(new LinkInfoImpl(context, classDoc,
bpatel@182: doc.name(), label, strong));
duke@1: } else {
duke@1: return label;
duke@1: }
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Return the link for the given member.
bpatel@766: *
bpatel@766: * @param context the id of the context where the link will be added
bpatel@766: * @param classDoc the classDoc that we should link to. This is not
bpatel@766: * necessarily equal to doc.containingClass(). We may be
bpatel@766: * inheriting comments
bpatel@766: * @param doc the member being linked to
bpatel@766: * @param label the label for the link
bpatel@766: * @return the link for the given member
bpatel@766: */
bpatel@766: public Content getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
bpatel@766: String label) {
bpatel@766: if (! (doc.isIncluded() ||
bpatel@766: Util.isLinkable(classDoc, configuration()))) {
bpatel@766: return new StringContent(label);
bpatel@766: } else if (doc instanceof ExecutableMemberDoc) {
bpatel@766: ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
bpatel@766: return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
bpatel@766: getAnchor(emd), label, false)));
bpatel@766: } else if (doc instanceof MemberDoc) {
bpatel@766: return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
bpatel@766: doc.name(), label, false)));
bpatel@766: } else {
bpatel@766: return new StringContent(label);
bpatel@766: }
bpatel@766: }
bpatel@766:
duke@1: public void anchor(ExecutableMemberDoc emd) {
duke@1: anchor(getAnchor(emd));
duke@1: }
duke@1:
duke@1: public String getAnchor(ExecutableMemberDoc emd) {
duke@1: StringBuilder signature = new StringBuilder(emd.signature());
duke@1: StringBuilder signatureParsed = new StringBuilder();
duke@1: int counter = 0;
duke@1: for (int i = 0; i < signature.length(); i++) {
duke@1: char c = signature.charAt(i);
duke@1: if (c == '<') {
duke@1: counter++;
duke@1: } else if (c == '>') {
duke@1: counter--;
duke@1: } else if (counter == 0) {
duke@1: signatureParsed.append(c);
duke@1: }
duke@1: }
duke@1: return emd.name() + signatureParsed.toString();
duke@1: }
duke@1:
duke@1: public String seeTagToString(SeeTag see) {
duke@1: String tagName = see.name();
duke@1: if (! (tagName.startsWith("@link") || tagName.equals("@see"))) {
duke@1: return "";
duke@1: }
duke@1: StringBuffer result = new StringBuffer();
duke@1: boolean isplaintext = tagName.toLowerCase().equals("@linkplain");
duke@1: String label = see.label();
duke@1: label = (label.length() > 0)?
duke@1: ((isplaintext) ? label :
duke@1: getCode() + label + getCodeEnd()):"";
duke@1: String seetext = replaceDocRootDir(see.text());
duke@1:
duke@1: //Check if @see is an href or "string"
duke@1: if (seetext.startsWith("<") || seetext.startsWith("\"")) {
duke@1: result.append(seetext);
duke@1: return result.toString();
duke@1: }
duke@1:
duke@1: //The text from the @see tag. We will output this text when a label is not specified.
duke@1: String text = (isplaintext) ? seetext : getCode() + seetext + getCodeEnd();
duke@1:
duke@1: ClassDoc refClass = see.referencedClass();
duke@1: String refClassName = see.referencedClassName();
duke@1: MemberDoc refMem = see.referencedMember();
duke@1: String refMemName = see.referencedMemberName();
duke@1: if (refClass == null) {
duke@1: //@see is not referencing an included class
duke@1: PackageDoc refPackage = see.referencedPackage();
duke@1: if (refPackage != null && refPackage.isIncluded()) {
duke@1: //@see is referencing an included package
duke@1: String packageName = isplaintext ? refPackage.name() :
duke@1: getCode() + refPackage.name() + getCodeEnd();
bpatel@766: result.append(getPackageLinkString(refPackage,
duke@1: label.length() == 0 ? packageName : label, false));
duke@1: } else {
duke@1: //@see is not referencing an included class or package. Check for cross links.
duke@1: String classCrossLink, packageCrossLink = getCrossPackageLink(refClassName);
duke@1: if (packageCrossLink != null) {
duke@1: //Package cross link found
bpatel@766: result.append(getHyperLinkString(packageCrossLink, "",
duke@1: (label.length() == 0)? text : label, false));
duke@1: } else if ((classCrossLink = getCrossClassLink(refClassName,
duke@1: refMemName, label, false, "", ! isplaintext)) != null) {
duke@1: //Class cross link found (possiblly to a member in the class)
duke@1: result.append(classCrossLink);
duke@1: } else {
duke@1: //No cross link found so print warning
duke@1: configuration.getDocletSpecificMsg().warning(see.position(), "doclet.see.class_or_package_not_found",
duke@1: tagName, seetext);
duke@1: result.append((label.length() == 0)? text: label);
duke@1: }
duke@1: }
duke@1: } else if (refMemName == null) {
duke@1: // Must be a class reference since refClass is not null and refMemName is null.
duke@1: if (label.length() == 0) {
duke@1: label = (isplaintext) ? refClass.name() : getCode() + refClass.name() + getCodeEnd();
duke@1: result.append(getLink(new LinkInfoImpl(refClass, label)));
duke@1: } else {
duke@1: result.append(getLink(new LinkInfoImpl(refClass, label)));
duke@1: }
duke@1: } else if (refMem == null) {
duke@1: // Must be a member reference since refClass is not null and refMemName is not null.
duke@1: // However, refMem is null, so this referenced member does not exist.
duke@1: result.append((label.length() == 0)? text: label);
duke@1: } else {
duke@1: // Must be a member reference since refClass is not null and refMemName is not null.
duke@1: // refMem is not null, so this @see tag must be referencing a valid member.
duke@1: ClassDoc containing = refMem.containingClass();
duke@1: if (see.text().trim().startsWith("#") &&
duke@1: ! (containing.isPublic() ||
duke@1: Util.isLinkable(containing, configuration()))) {
duke@1: // Since the link is relative and the holder is not even being
duke@1: // documented, this must be an inherited link. Redirect it.
duke@1: // The current class either overrides the referenced member or
duke@1: // inherits it automatically.
jjg@405: if (this instanceof ClassWriterImpl) {
jjg@405: containing = ((ClassWriterImpl) this).getClassDoc();
jjg@405: } else if (!containing.isPublic()){
jjg@405: configuration.getDocletSpecificMsg().warning(
jjg@405: see.position(), "doclet.see.class_or_package_not_accessible",
jjg@405: tagName, containing.qualifiedName());
jjg@405: } else {
jjg@405: configuration.getDocletSpecificMsg().warning(
jjg@405: see.position(), "doclet.see.class_or_package_not_found",
jjg@405: tagName, seetext);
jjg@405: }
duke@1: }
duke@1: if (configuration.currentcd != containing) {
duke@1: refMemName = containing.name() + "." + refMemName;
duke@1: }
duke@1: if (refMem instanceof ExecutableMemberDoc) {
duke@1: if (refMemName.indexOf('(') < 0) {
duke@1: refMemName += ((ExecutableMemberDoc)refMem).signature();
duke@1: }
duke@1: }
duke@1: text = (isplaintext) ?
bpatel@981: refMemName : getCode() + Util.escapeHtmlChars(refMemName) + getCodeEnd();
duke@1:
duke@1: result.append(getDocLink(LinkInfoImpl.CONTEXT_SEE_TAG, containing,
duke@1: refMem, (label.length() == 0)? text: label, false));
duke@1: }
duke@1: return result.toString();
duke@1: }
duke@1:
duke@1: public void printInlineComment(Doc doc, Tag tag) {
duke@1: printCommentTags(doc, tag.inlineTags(), false, false);
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Add the inline comment.
bpatel@766: *
bpatel@766: * @param doc the doc for which the inline comment will be added
bpatel@766: * @param tag the inline tag to be added
bpatel@766: * @param htmltree the content tree to which the comment will be added
bpatel@766: */
bpatel@766: public void addInlineComment(Doc doc, Tag tag, Content htmltree) {
bpatel@766: addCommentTags(doc, tag.inlineTags(), false, false, htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printInlineDeprecatedComment(Doc doc, Tag tag) {
duke@1: printCommentTags(doc, tag.inlineTags(), true, false);
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Add the inline deprecated comment.
bpatel@766: *
bpatel@766: * @param doc the doc for which the inline deprecated comment will be added
bpatel@766: * @param tag the inline tag to be added
bpatel@766: * @param htmltree the content tree to which the comment will be added
bpatel@766: */
bpatel@766: public void addInlineDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
bpatel@766: addCommentTags(doc, tag.inlineTags(), true, false, htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printSummaryComment(Doc doc) {
duke@1: printSummaryComment(doc, doc.firstSentenceTags());
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Adds the summary content.
bpatel@766: *
bpatel@766: * @param doc the doc for which the summary will be generated
bpatel@766: * @param htmltree the documentation tree to which the summary will be added
bpatel@766: */
bpatel@766: public void addSummaryComment(Doc doc, Content htmltree) {
bpatel@766: addSummaryComment(doc, doc.firstSentenceTags(), htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printSummaryComment(Doc doc, Tag[] firstSentenceTags) {
duke@1: printCommentTags(doc, firstSentenceTags, false, true);
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Adds the summary content.
bpatel@766: *
bpatel@766: * @param doc the doc for which the summary will be generated
bpatel@766: * @param firstSentenceTags the first sentence tags for the doc
bpatel@766: * @param htmltree the documentation tree to which the summary will be added
bpatel@766: */
bpatel@766: public void addSummaryComment(Doc doc, Tag[] firstSentenceTags, Content htmltree) {
bpatel@766: addCommentTags(doc, firstSentenceTags, false, true, htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printSummaryDeprecatedComment(Doc doc) {
duke@1: printCommentTags(doc, doc.firstSentenceTags(), true, true);
duke@1: }
duke@1:
duke@1: public void printSummaryDeprecatedComment(Doc doc, Tag tag) {
duke@1: printCommentTags(doc, tag.firstSentenceTags(), true, true);
duke@1: }
duke@1:
bpatel@766: public void addSummaryDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
bpatel@766: addCommentTags(doc, tag.firstSentenceTags(), true, true, htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printInlineComment(Doc doc) {
duke@1: printCommentTags(doc, doc.inlineTags(), false, false);
duke@1: p();
duke@1: }
duke@1:
bpatel@766: /**
bpatel@766: * Adds the inline comment.
bpatel@766: *
bpatel@766: * @param doc the doc for which the inline comments will be generated
bpatel@766: * @param htmltree the documentation tree to which the inline comments will be added
bpatel@766: */
bpatel@766: public void addInlineComment(Doc doc, Content htmltree) {
bpatel@766: addCommentTags(doc, doc.inlineTags(), false, false, htmltree);
bpatel@766: }
bpatel@766:
duke@1: public void printInlineDeprecatedComment(Doc doc) {
duke@1: printCommentTags(doc, doc.inlineTags(), true, false);
duke@1: }
duke@1:
duke@1: private void printCommentTags(Doc doc, Tag[] tags, boolean depr, boolean first) {
duke@1: if(configuration.nocomment){
duke@1: return;
duke@1: }
duke@1: if (depr) {
duke@1: italic();
duke@1: }
duke@1: String result = commentTagsToString(null, doc, tags, first);
duke@1: print(result);
duke@1: if (depr) {
duke@1: italicEnd();
duke@1: }
duke@1: if (tags.length == 0) {
duke@1: space();
duke@1: }
duke@1: }
duke@1:
duke@1: /**
bpatel@766: * Adds the comment tags.
bpatel@766: *
bpatel@766: * @param doc the doc for which the comment tags will be generated
bpatel@766: * @param tags the first sentence tags for the doc
bpatel@766: * @param depr true if it is deprecated
bpatel@766: * @param first true if the first sentenge tags should be added
bpatel@766: * @param htmltree the documentation tree to which the comment tags will be added
bpatel@766: */
bpatel@766: private void addCommentTags(Doc doc, Tag[] tags, boolean depr,
bpatel@766: boolean first, Content htmltree) {
bpatel@766: if(configuration.nocomment){
bpatel@766: return;
bpatel@766: }
bpatel@766: Content div;
bpatel@766: Content result = new RawHtml(commentTagsToString(null, doc, tags, first));
bpatel@766: if (depr) {
bpatel@766: Content italic = HtmlTree.I(result);
bpatel@766: div = HtmlTree.DIV(HtmlStyle.block, italic);
bpatel@766: htmltree.addContent(div);
bpatel@766: }
bpatel@766: else {
bpatel@766: div = HtmlTree.DIV(HtmlStyle.block, result);
bpatel@766: htmltree.addContent(div);
bpatel@766: }
bpatel@766: if (tags.length == 0) {
bpatel@766: htmltree.addContent(getSpace());
bpatel@766: }
bpatel@766: }
bpatel@766:
bpatel@766: /**
duke@1: * Converts inline tags and text to text strings, expanding the
duke@1: * inline tags along the way. Called wherever text can contain
duke@1: * an inline tag, such as in comments or in free-form text arguments
duke@1: * to non-inline tags.
duke@1: *
duke@1: * @param holderTag specific tag where comment resides
duke@1: * @param doc specific doc where comment resides
duke@1: * @param tags array of text tags and inline tags (often alternating)
duke@1: * present in the text of interest for this doc
duke@1: * @param isFirstSentence true if text is first sentence
duke@1: */
duke@1: public String commentTagsToString(Tag holderTag, Doc doc, Tag[] tags,
duke@1: boolean isFirstSentence) {
jjg@910: StringBuilder result = new StringBuilder();
bpatel@997: boolean textTagChange = false;
duke@1: // Array of all possible inline tags for this javadoc run
duke@1: configuration.tagletManager.checkTags(doc, tags, true);
duke@1: for (int i = 0; i < tags.length; i++) {
duke@1: Tag tagelem = tags[i];
duke@1: String tagName = tagelem.name();
duke@1: if (tagelem instanceof SeeTag) {
duke@1: result.append(seeTagToString((SeeTag)tagelem));
duke@1: } else if (! tagName.equals("Text")) {
duke@1: int originalLength = result.length();
duke@1: TagletOutput output = TagletWriter.getInlineTagOuput(
duke@1: configuration.tagletManager, holderTag,
jjg@74: tagelem, getTagletWriterInstance(isFirstSentence));
duke@1: result.append(output == null ? "" : output.toString());
duke@1: if (originalLength == 0 && isFirstSentence && tagelem.name().equals("@inheritDoc") && result.length() > 0) {
duke@1: break;
bpatel@997: } else if (configuration.docrootparent.length() > 0 &&
bpatel@997: tagelem.name().equals("@docRoot") &&
bpatel@997: ((tags[i + 1]).text()).startsWith("/..")) {
bpatel@997: //If Xdocrootparent switch ON, set the flag to remove the /.. occurance after
bpatel@997: //{@docRoot} tag in the very next Text tag.
bpatel@997: textTagChange = true;
bpatel@997: continue;
duke@1: } else {
bpatel@997: continue;
duke@1: }
duke@1: } else {
bpatel@997: String text = tagelem.text();
bpatel@997: //If Xdocrootparent switch ON, remove the /.. occurance after {@docRoot} tag.
bpatel@997: if (textTagChange) {
bpatel@997: text = text.replaceFirst("/..", "");
bpatel@997: textTagChange = false;
bpatel@997: }
duke@1: //This is just a regular text tag. The text may contain html links ()
duke@1: //or inline tag {@docRoot}, which will be handled as special cases.
bpatel@997: text = redirectRelativeLinks(tagelem.holder(), text);
duke@1:
duke@1: // Replace @docRoot only if not represented by an instance of DocRootTaglet,
duke@1: // that is, only if it was not present in a source file doc comment.
duke@1: // This happens when inserted by the doclet (a few lines
duke@1: // above in this method). [It might also happen when passed in on the command
duke@1: // line as a text argument to an option (like -header).]
duke@1: text = replaceDocRootDir(text);
duke@1: if (isFirstSentence) {
duke@1: text = removeNonInlineHtmlTags(text);
duke@1: }
duke@1: StringTokenizer lines = new StringTokenizer(text, "\r\n", true);
duke@1: StringBuffer textBuff = new StringBuffer();
duke@1: while (lines.hasMoreTokens()) {
jjg@910: StringBuilder line = new StringBuilder(lines.nextToken());
duke@1: Util.replaceTabs(configuration.sourcetab, line);
duke@1: textBuff.append(line.toString());
duke@1: }
duke@1: result.append(textBuff);
duke@1: }
duke@1: }
duke@1: return result.toString();
duke@1: }
duke@1:
duke@1: /**
duke@1: * Return true if relative links should not be redirected.
duke@1: *
duke@1: * @return Return true if a relative link should not be redirected.
duke@1: */
duke@1: private boolean shouldNotRedirectRelativeLinks() {
duke@1: return this instanceof AnnotationTypeWriter ||
duke@1: this instanceof ClassWriter ||
duke@1: this instanceof PackageSummaryWriter;
duke@1: }
duke@1:
duke@1: /**
duke@1: * Suppose a piece of documentation has a relative link. When you copy
duke@1: * that documetation to another place such as the index or class-use page,
duke@1: * that relative link will no longer work. We should redirect those links
duke@1: * so that they will work again.
duke@1: * duke@1: * For example, suppose com.sun.javadoc.RootDoc has this link: jjg@1326: * {@literal The package Page } duke@1: *
duke@1: * If this link appeared in the index, we would redirect
duke@1: * the link like this:
duke@1: *
jjg@1326: * {@literal The package Page}
duke@1: *
duke@1: * @param doc the Doc object whose documentation is being written.
duke@1: * @param text the text being written.
duke@1: *
duke@1: * @return the text, with all the relative links redirected to work.
duke@1: */
duke@1: private String redirectRelativeLinks(Doc doc, String text) {
duke@1: if (doc == null || shouldNotRedirectRelativeLinks()) {
duke@1: return text;
duke@1: }
duke@1:
duke@1: String redirectPathFromRoot;
duke@1: if (doc instanceof ClassDoc) {
duke@1: redirectPathFromRoot = DirectoryManager.getDirectoryPath(((ClassDoc) doc).containingPackage());
duke@1: } else if (doc instanceof MemberDoc) {
duke@1: redirectPathFromRoot = DirectoryManager.getDirectoryPath(((MemberDoc) doc).containingPackage());
duke@1: } else if (doc instanceof PackageDoc) {
duke@1: redirectPathFromRoot = DirectoryManager.getDirectoryPath((PackageDoc) doc);
duke@1: } else {
duke@1: return text;
duke@1: }
duke@1:
bpatel@766: if (! redirectPathFromRoot.endsWith(DirectoryManager.URL_FILE_SEPARATOR)) {
bpatel@766: redirectPathFromRoot += DirectoryManager.URL_FILE_SEPARATOR;
duke@1: }
duke@1:
duke@1: //Redirect all relative links.
duke@1: int end, begin = text.toLowerCase().indexOf("= 0){
duke@1: StringBuffer textBuff = new StringBuffer(text);
duke@1:
duke@1: while(begin >=0){
duke@1: if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
duke@1: begin = textBuff.toString().toLowerCase().indexOf("", begin +1);
duke@1: if(begin == 0){
duke@1: //Link has no equal symbol.
duke@1: configuration.root.printWarning(
duke@1: doc.position(),
duke@1: configuration.getText("doclet.malformed_html_link_tag", text));
duke@1: break;
duke@1: }
duke@1: if (end == -1) {
duke@1: //Break without warning. This tag is not necessarily malformed. The text
duke@1: //might be missing '>' character because the href has an inline tag.
duke@1: break;
duke@1: }
duke@1: if(textBuff.substring(begin, end).indexOf("\"") != -1){
duke@1: begin = textBuff.indexOf("\"", begin) + 1;
duke@1: end = textBuff.indexOf("\"", begin +1);
duke@1: if(begin == 0 || end == -1){
duke@1: //Link is missing a quote.
duke@1: break;
duke@1: }
duke@1: }
duke@1: String relativeLink = textBuff.substring(begin, end);
duke@1: if(!(relativeLink.toLowerCase().startsWith("mailto:") ||
duke@1: relativeLink.toLowerCase().startsWith("http:") ||
duke@1: relativeLink.toLowerCase().startsWith("https:") ||
duke@1: relativeLink.toLowerCase().startsWith("file:"))){
duke@1: relativeLink = "{@"+(new DocRootTaglet()).getName() + "}"
duke@1: + redirectPathFromRoot
duke@1: + relativeLink;
duke@1: textBuff.replace(begin, end, relativeLink);
duke@1: }
duke@1: begin = textBuff.toString().toLowerCase().indexOf("", "", " ", " | ",
duke@1: "", " | ", "", " ", duke@1: "", "", "", "", duke@1: "", "", "", "", duke@1: "", "", "", "", duke@1: "", "", "", duke@1: " ", duke@1: " ", "", duke@1: "
", " | ",
duke@1: "", " | ", "", " ", duke@1: "", "", "", "", duke@1: "", "", "", "", duke@1: "", "", "", "", duke@1: "", "", "", duke@1: " ", duke@1: " ", "", duke@1: " |