src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java

Mon, 18 Apr 2011 15:39:16 -0700

author
bpatel
date
Mon, 18 Apr 2011 15:39:16 -0700
changeset 981
bbd053476ec3
parent 972
694ff82ca68e
child 995
62bc3775d5bb
permissions
-rw-r--r--

6758050: javadoc handles nested generic types incorrectly
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.doclets.formats.html;
    28 import java.io.*;
    29 import java.text.SimpleDateFormat;
    30 import java.util.*;
    32 import com.sun.javadoc.*;
    33 import com.sun.tools.doclets.formats.html.markup.*;
    34 import com.sun.tools.doclets.internal.toolkit.*;
    35 import com.sun.tools.doclets.internal.toolkit.util.*;
    36 import com.sun.tools.doclets.internal.toolkit.taglets.*;
    38 /**
    39  * Class for the Html Format Code Generation specific to JavaDoc.
    40  * This Class contains methods related to the Html Code Generation which
    41  * are used extensively while generating the entire documentation.
    42  *
    43  * @since 1.2
    44  * @author Atul M Dambalkar
    45  * @author Robert Field
    46  * @author Bhavesh Patel (Modified)
    47  */
    48 public class HtmlDocletWriter extends HtmlDocWriter {
    50     /**
    51      * Relative path from the file getting generated to the destination
    52      * directory. For example, if the file getting generated is
    53      * "java/lang/Object.html", then the relative path string is "../../".
    54      * This string can be empty if the file getting generated is in
    55      * the destination directory.
    56      */
    57     public String relativePath = "";
    59     /**
    60      * Same as relativepath, but normalized to never be empty or
    61      * end with a slash.
    62      */
    63     public String relativepathNoSlash = "";
    65     /**
    66      * Platform-dependent directory path from the current or the
    67      * destination directory to the file getting generated.
    68      * Used when creating the file.
    69      * For example, if the file getting generated is
    70      * "java/lang/Object.html", then the path string is "java/lang".
    71      */
    72     public String path = "";
    74     /**
    75      * Name of the file getting generated. If the file getting generated is
    76      * "java/lang/Object.html", then the filename is "Object.html".
    77      */
    78     public String filename = "";
    80     /**
    81      * The display length used for indentation while generating the class page.
    82      */
    83     public int displayLength = 0;
    85     /**
    86      * The global configuration information for this run.
    87      */
    88     public ConfigurationImpl configuration;
    90     /**
    91      * To check whether annotation heading is printed or not.
    92      */
    93     protected boolean printedAnnotationHeading = false;
    95     /**
    96      * Constructor to construct the HtmlStandardWriter object.
    97      *
    98      * @param filename File to be generated.
    99      */
   100     public HtmlDocletWriter(ConfigurationImpl configuration,
   101                               String filename) throws IOException {
   102         super(configuration, filename);
   103         this.configuration = configuration;
   104         this.filename = filename;
   105     }
   107     /**
   108      * Constructor to construct the HtmlStandardWriter object.
   109      *
   110      * @param path         Platform-dependent {@link #path} used when
   111      *                     creating file.
   112      * @param filename     Name of file to be generated.
   113      * @param relativePath Value for the variable {@link #relativePath}.
   114      */
   115     public HtmlDocletWriter(ConfigurationImpl configuration,
   116                               String path, String filename,
   117                               String relativePath) throws IOException {
   118         super(configuration, path, filename);
   119         this.configuration = configuration;
   120         this.path = path;
   121         this.relativePath = relativePath;
   122         this.relativepathNoSlash =
   123             DirectoryManager.getPathNoTrailingSlash(this.relativePath);
   124         this.filename = filename;
   125     }
   127     /**
   128      * Replace {@docRoot} tag used in options that accept HTML text, such
   129      * as -header, -footer, -top and -bottom, and when converting a relative
   130      * HREF where commentTagsToString inserts a {@docRoot} where one was
   131      * missing.  (Also see DocRootTaglet for {@docRoot} tags in doc
   132      * comments.)
   133      * <p>
   134      * Replace {&#064;docRoot} tag in htmlstr with the relative path to the
   135      * destination directory from the directory where the file is being
   136      * written, looping to handle all such tags in htmlstr.
   137      * <p>
   138      * For example, for "-d docs" and -header containing {&#064;docRoot}, when
   139      * the HTML page for source file p/C1.java is being generated, the
   140      * {&#064;docRoot} tag would be inserted into the header as "../",
   141      * the relative path from docs/p/ to docs/ (the document root).
   142      * <p>
   143      * Note: This doc comment was written with '&amp;#064;' representing '@'
   144      * to prevent the inline tag from being interpreted.
   145      */
   146     public String replaceDocRootDir(String htmlstr) {
   147         // Return if no inline tags exist
   148         int index = htmlstr.indexOf("{@");
   149         if (index < 0) {
   150             return htmlstr;
   151         }
   152         String lowerHtml = htmlstr.toLowerCase();
   153         // Return index of first occurrence of {@docroot}
   154         // Note: {@docRoot} is not case sensitive when passed in w/command line option
   155         index = lowerHtml.indexOf("{@docroot}", index);
   156         if (index < 0) {
   157             return htmlstr;
   158         }
   159         StringBuilder buf = new StringBuilder();
   160         int previndex = 0;
   161         while (true) {
   162             // Search for lowercase version of {@docRoot}
   163             index = lowerHtml.indexOf("{@docroot}", previndex);
   164             // If next {@docRoot} tag not found, append rest of htmlstr and exit loop
   165             if (index < 0) {
   166                 buf.append(htmlstr.substring(previndex));
   167                 break;
   168             }
   169             // If next {@docroot} tag found, append htmlstr up to start of tag
   170             buf.append(htmlstr.substring(previndex, index));
   171             previndex = index + 10;  // length for {@docroot} string
   172             // Insert relative path where {@docRoot} was located
   173             buf.append(relativepathNoSlash);
   174             // Append slash if next character is not a slash
   175             if (relativepathNoSlash.length() > 0 && previndex < htmlstr.length()
   176                     && htmlstr.charAt(previndex) != '/') {
   177                 buf.append(DirectoryManager.URL_FILE_SEPARATOR);
   178             }
   179         }
   180         return buf.toString();
   181     }
   183     /**
   184      * Print Html Hyper Link, with target frame.  This
   185      * link will only appear if page is not in a frame.
   186      *
   187      * @param link String name of the file.
   188      * @param where Position in the file
   189      * @param target Name of the target frame.
   190      * @param label Tag for the link.
   191      * @param strong Whether the label should be strong or not?
   192      */
   193     public void printNoFramesTargetHyperLink(String link, String where,
   194                                                String target, String label,
   195                                                boolean strong) {
   196         script();
   197         println("  <!--");
   198         println("  if(window==top) {");
   199         println("    document.writeln('"
   200             + getHyperLinkString(link, where, label, strong, "", "", target) + "');");
   201         println("  }");
   202         println("  //-->");
   203         scriptEnd();
   204         noScript();
   205         println("  " + getHyperLinkString(link, where, label, strong, "", "", target));
   206         noScriptEnd();
   207         println(DocletConstants.NL);
   208     }
   210     /**
   211      * Get the script to show or hide the All classes link.
   212      *
   213      * @param id id of the element to show or hide
   214      * @return a content tree for the script
   215      */
   216     public Content getAllClassesLinkScript(String id) {
   217         HtmlTree script = new HtmlTree(HtmlTag.SCRIPT);
   218         script.addAttr(HtmlAttr.TYPE, "text/javascript");
   219         String scriptCode = "<!--" + DocletConstants.NL +
   220                 "  allClassesLink = document.getElementById(\"" + id + "\");" + DocletConstants.NL +
   221                 "  if(window==top) {" + DocletConstants.NL +
   222                 "    allClassesLink.style.display = \"block\";" + DocletConstants.NL +
   223                 "  }" + DocletConstants.NL +
   224                 "  else {" + DocletConstants.NL +
   225                 "    allClassesLink.style.display = \"none\";" + DocletConstants.NL +
   226                 "  }" + DocletConstants.NL +
   227                 "  //-->" + DocletConstants.NL;
   228         Content scriptContent = new RawHtml(scriptCode);
   229         script.addContent(scriptContent);
   230         Content div = HtmlTree.DIV(script);
   231         return div;
   232     }
   234     /**
   235      * Add method information.
   236      *
   237      * @param method the method to be documented
   238      * @param dl the content tree to which the method information will be added
   239      */
   240     private void addMethodInfo(MethodDoc method, Content dl) {
   241         ClassDoc[] intfacs = method.containingClass().interfaces();
   242         MethodDoc overriddenMethod = method.overriddenMethod();
   243         // Check whether there is any implementation or overridden info to be
   244         // printed. If no overridden or implementation info needs to be
   245         // printed, do not print this section.
   246         if ((intfacs.length > 0 &&
   247                 new ImplementedMethods(method, this.configuration).build().length > 0) ||
   248                 overriddenMethod != null) {
   249             MethodWriterImpl.addImplementsInfo(this, method, dl);
   250             if (overriddenMethod != null) {
   251                 MethodWriterImpl.addOverridden(this,
   252                         method.overriddenType(), overriddenMethod, dl);
   253             }
   254         }
   255     }
   257     /**
   258      * Adds the tags information.
   259      *
   260      * @param doc the doc for which the tags will be generated
   261      * @param htmltree the documentation tree to which the tags will be added
   262      */
   263     protected void addTagsInfo(Doc doc, Content htmltree) {
   264         if (configuration.nocomment) {
   265             return;
   266         }
   267         Content dl = new HtmlTree(HtmlTag.DL);
   268         if (doc instanceof MethodDoc) {
   269             addMethodInfo((MethodDoc) doc, dl);
   270         }
   271         TagletOutputImpl output = new TagletOutputImpl("");
   272         TagletWriter.genTagOuput(configuration.tagletManager, doc,
   273             configuration.tagletManager.getCustomTags(doc),
   274                 getTagletWriterInstance(false), output);
   275         String outputString = output.toString().trim();
   276         if (!outputString.isEmpty()) {
   277             Content resultString = new RawHtml(outputString);
   278             dl.addContent(resultString);
   279         }
   280         htmltree.addContent(dl);
   281     }
   283     /**
   284      * Check whether there are any tags for Serialization Overview
   285      * section to be printed.
   286      *
   287      * @param field the FieldDoc object to check for tags.
   288      * @return true if there are tags to be printed else return false.
   289      */
   290     protected boolean hasSerializationOverviewTags(FieldDoc field) {
   291         TagletOutputImpl output = new TagletOutputImpl("");
   292         TagletWriter.genTagOuput(configuration.tagletManager, field,
   293             configuration.tagletManager.getCustomTags(field),
   294                 getTagletWriterInstance(false), output);
   295         return (!output.toString().trim().isEmpty());
   296     }
   298     /**
   299      * Returns a TagletWriter that knows how to write HTML.
   300      *
   301      * @return a TagletWriter that knows how to write HTML.
   302      */
   303     public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
   304         return new TagletWriterImpl(this, isFirstSentence);
   305     }
   307     protected void printTagsInfoHeader() {
   308         dl();
   309     }
   311     protected void printTagsInfoFooter() {
   312         dlEnd();
   313     }
   315     /**
   316      * Get Package link, with target frame.
   317      *
   318      * @param pd The link will be to the "package-summary.html" page for this package
   319      * @param target name of the target frame
   320      * @param label tag for the link
   321      * @return a content for the target package link
   322      */
   323     public Content getTargetPackageLink(PackageDoc pd, String target,
   324             Content label) {
   325         return getHyperLink(pathString(pd, "package-summary.html"), "", label, "", target);
   326     }
   328     /**
   329      * Print the html file header. Also print Html page title and stylesheet
   330      * default properties.
   331      *
   332      * @param title         String window title to go in the &lt;TITLE&gt; tag
   333      * @param metakeywords  Array of String keywords for META tag.  Each element
   334      *                      of the array is assigned to a separate META tag.
   335      *                      Pass in null for no array.
   336      * @param includeScript boolean true if printing windowtitle script.
   337      *             False for files that appear in the left-hand frames.
   338      */
   339     public void printHtmlHeader(String title, String[] metakeywords,
   340             boolean includeScript) {
   341         println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " +
   342                     "Transitional//EN\" " +
   343                     "\"http://www.w3.org/TR/html4/loose.dtd\">");
   344         println("<!--NewPage-->");
   345         html();
   346         head();
   347         if (! configuration.notimestamp) {
   348             print("<!-- Generated by javadoc (build " + ConfigurationImpl.BUILD_DATE + ") on ");
   349             print(today());
   350             println(" -->");
   351         }
   352         if (configuration.charset.length() > 0) {
   353             println("<META http-equiv=\"Content-Type\" content=\"text/html; "
   354                         + "charset=" + configuration.charset + "\">");
   355         }
   356         if ( configuration.windowtitle.length() > 0 ) {
   357             title += " (" + configuration.windowtitle  + ")";
   358         }
   359         title(title);
   360         println(title);
   361         titleEnd();
   362         println("");
   363         if (! configuration.notimestamp) {
   364                 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
   365                 println("<META NAME=\"date\" "
   366                                     + "CONTENT=\"" + dateFormat.format(new Date()) + "\">");
   367         }
   368         if ( metakeywords != null ) {
   369             for ( int i=0; i < metakeywords.length; i++ ) {
   370                 println("<META NAME=\"keywords\" "
   371                             + "CONTENT=\"" + metakeywords[i] + "\">");
   372             }
   373         }
   374         println("");
   375         printStyleSheetProperties();
   376         println("");
   377         // Don't print windowtitle script for overview-frame, allclasses-frame
   378         // and package-frame
   379         if (includeScript) {
   380             printWinTitleScript(title);
   381         }
   382         println("");
   383         headEnd();
   384         println("");
   385         body("white", includeScript);
   386     }
   388     /**
   389      * Generates the HTML document tree and prints it out.
   390      *
   391      * @param metakeywords Array of String keywords for META tag. Each element
   392      *                     of the array is assigned to a separate META tag.
   393      *                     Pass in null for no array
   394      * @param includeScript true if printing windowtitle script
   395      *                      false for files that appear in the left-hand frames
   396      * @param body the body htmltree to be included in the document
   397      */
   398     public void printHtmlDocument(String[] metakeywords, boolean includeScript,
   399             Content body) {
   400         Content htmlDocType = DocType.Transitional();
   401         Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
   402         Content head = new HtmlTree(HtmlTag.HEAD);
   403         if (!configuration.notimestamp) {
   404             Content headComment = new Comment("Generated by javadoc (version " +
   405                     ConfigurationImpl.BUILD_DATE + ") on " + today());
   406             head.addContent(headComment);
   407         }
   408         if (configuration.charset.length() > 0) {
   409             Content meta = HtmlTree.META("Content-Type", "text/html",
   410                     configuration.charset);
   411             head.addContent(meta);
   412         }
   413         head.addContent(getTitle());
   414         if (!configuration.notimestamp) {
   415             SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
   416             Content meta = HtmlTree.META("date", dateFormat.format(new Date()));
   417             head.addContent(meta);
   418         }
   419         if (metakeywords != null) {
   420             for (int i=0; i < metakeywords.length; i++) {
   421                 Content meta = HtmlTree.META("keywords", metakeywords[i]);
   422                 head.addContent(meta);
   423             }
   424         }
   425         head.addContent(getStyleSheetProperties());
   426         Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
   427                 head, body);
   428         Content htmlDocument = new HtmlDocument(htmlDocType,
   429                 htmlComment, htmlTree);
   430         print(htmlDocument.toString());
   431     }
   433     /**
   434      * Get the window title.
   435      *
   436      * @param title the title string to construct the complete window title
   437      * @return the window title string
   438      */
   439     public String getWindowTitle(String title) {
   440         if (configuration.windowtitle.length() > 0) {
   441             title += " (" + configuration.windowtitle  + ")";
   442         }
   443         return title;
   444     }
   446     /**
   447      * Print user specified header and the footer.
   448      *
   449      * @param header if true print the user provided header else print the
   450      * user provided footer.
   451      */
   452     public void printUserHeaderFooter(boolean header) {
   453         em();
   454         if (header) {
   455             print(replaceDocRootDir(configuration.header));
   456         } else {
   457             if (configuration.footer.length() != 0) {
   458                 print(replaceDocRootDir(configuration.footer));
   459             } else {
   460                 print(replaceDocRootDir(configuration.header));
   461             }
   462         }
   463         emEnd();
   464     }
   466     /**
   467      * Get user specified header and the footer.
   468      *
   469      * @param header if true print the user provided header else print the
   470      * user provided footer.
   471      */
   472     public Content getUserHeaderFooter(boolean header) {
   473         String content;
   474         if (header) {
   475             content = replaceDocRootDir(configuration.header);
   476         } else {
   477             if (configuration.footer.length() != 0) {
   478                 content = replaceDocRootDir(configuration.footer);
   479             } else {
   480                 content = replaceDocRootDir(configuration.header);
   481             }
   482         }
   483         Content rawContent = new RawHtml(content);
   484         Content em = HtmlTree.EM(rawContent);
   485         return em;
   486     }
   488     /**
   489      * Print the user specified top.
   490      */
   491     public void printTop() {
   492         print(replaceDocRootDir(configuration.top));
   493         hr();
   494     }
   496     /**
   497      * Adds the user specified top.
   498      *
   499      * @param body the content tree to which user specified top will be added
   500      */
   501     public void addTop(Content body) {
   502         Content top = new RawHtml(replaceDocRootDir(configuration.top));
   503         body.addContent(top);
   504     }
   506     /**
   507      * Print the user specified bottom.
   508      */
   509     public void printBottom() {
   510         hr();
   511         print(replaceDocRootDir(configuration.bottom));
   512     }
   514     /**
   515      * Adds the user specified bottom.
   516      *
   517      * @param body the content tree to which user specified bottom will be added
   518      */
   519     public void addBottom(Content body) {
   520         Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom));
   521         Content small = HtmlTree.SMALL(bottom);
   522         Content p = HtmlTree.P(HtmlStyle.legalCopy, small);
   523         body.addContent(p);
   524     }
   526     /**
   527      * Print the navigation bar for the Html page at the top and and the bottom.
   528      *
   529      * @param header If true print navigation bar at the top of the page else
   530      * print the nevigation bar at the bottom.
   531      */
   532     protected void navLinks(boolean header) {
   533         println("");
   534         if (!configuration.nonavbar) {
   535             if (header) {
   536                 println(DocletConstants.NL + "<!-- ========= START OF TOP NAVBAR ======= -->");
   537                 anchor("navbar_top");
   538                 println();
   539                 print(getHyperLinkString("", "skip-navbar_top", "", false, "",
   540                     configuration.getText("doclet.Skip_navigation_links"), ""));
   541             } else {
   542                 println(DocletConstants.NL + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
   543                 anchor("navbar_bottom");
   544                 println();
   545                 print(getHyperLinkString("", "skip-navbar_bottom", "", false, "",
   546                     configuration.getText("doclet.Skip_navigation_links"), ""));
   547             }
   548             table(0, "100%", 1, 0);
   549             tr();
   550             tdColspanBgcolorStyle(2, "#EEEEFF", "NavBarCell1");
   551             println("");
   552             if (header) {
   553                 anchor("navbar_top_firstrow");
   554             } else {
   555                 anchor("navbar_bottom_firstrow");
   556             }
   557             table(0, 0, 3);
   558             print("  ");
   559             trAlignVAlign("center", "top");
   561             if (configuration.createoverview) {
   562                 navLinkContents();
   563             }
   565             if (configuration.packages.length == 1) {
   566                 navLinkPackage(configuration.packages[0]);
   567             } else if (configuration.packages.length > 1) {
   568                 navLinkPackage();
   569             }
   571             navLinkClass();
   573             if(configuration.classuse) {
   574                 navLinkClassUse();
   575             }
   576             if(configuration.createtree) {
   577                 navLinkTree();
   578             }
   579             if(!(configuration.nodeprecated ||
   580                      configuration.nodeprecatedlist)) {
   581                 navLinkDeprecated();
   582             }
   583             if(configuration.createindex) {
   584                 navLinkIndex();
   585             }
   586             if (!configuration.nohelp) {
   587                 navLinkHelp();
   588             }
   589             print("  ");
   590             trEnd();
   591             tableEnd();
   592             tdEnd();
   594             tdAlignVAlignRowspan("right", "top", 3);
   596             printUserHeaderFooter(header);
   597             tdEnd();
   598             trEnd();
   599             println("");
   601             tr();
   602             tdBgcolorStyle("white", "NavBarCell2");
   603             font("-2");
   604             space();
   605             navLinkPrevious();
   606             space();
   607             println("");
   608             space();
   609             navLinkNext();
   610             fontEnd();
   611             tdEnd();
   613             tdBgcolorStyle("white", "NavBarCell2");
   614             font("-2");
   615             print("  ");
   616             navShowLists();
   617             print("  ");
   618             space();
   619             println("");
   620             space();
   621             navHideLists(filename);
   622             print("  ");
   623             space();
   624             println("");
   625             space();
   626             navLinkClassIndex();
   627             fontEnd();
   628             tdEnd();
   630             trEnd();
   632             printSummaryDetailLinks();
   634             tableEnd();
   635             if (header) {
   636                 aName("skip-navbar_top");
   637                 aEnd();
   638                 println(DocletConstants.NL + "<!-- ========= END OF TOP NAVBAR ========= -->");
   639             } else {
   640                 aName("skip-navbar_bottom");
   641                 aEnd();
   642                 println(DocletConstants.NL + "<!-- ======== END OF BOTTOM NAVBAR ======= -->");
   643             }
   644             println("");
   645         }
   646     }
   648     /**
   649      * Adds the navigation bar for the Html page at the top and and the bottom.
   650      *
   651      * @param header If true print navigation bar at the top of the page else
   652      * @param body the HtmlTree to which the nav links will be added
   653      */
   654     protected void addNavLinks(boolean header, Content body) {
   655         if (!configuration.nonavbar) {
   656             String allClassesId = "allclasses_";
   657             HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
   658             if (header) {
   659                 body.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
   660                 navDiv.addStyle(HtmlStyle.topNav);
   661                 allClassesId += "navbar_top";
   662                 Content a = getMarkerAnchor("navbar_top");
   663                 navDiv.addContent(a);
   664                 Content skipLinkContent = getHyperLink("",
   665                         "skip-navbar_top", HtmlTree.EMPTY, configuration.getText(
   666                         "doclet.Skip_navigation_links"), "");
   667                 navDiv.addContent(skipLinkContent);
   668             } else {
   669                 body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
   670                 navDiv.addStyle(HtmlStyle.bottomNav);
   671                 allClassesId += "navbar_bottom";
   672                 Content a = getMarkerAnchor("navbar_bottom");
   673                 navDiv.addContent(a);
   674                 Content skipLinkContent = getHyperLink("",
   675                         "skip-navbar_bottom", HtmlTree.EMPTY, configuration.getText(
   676                         "doclet.Skip_navigation_links"), "");
   677                 navDiv.addContent(skipLinkContent);
   678             }
   679             if (header) {
   680                 navDiv.addContent(getMarkerAnchor("navbar_top_firstrow"));
   681             } else {
   682                 navDiv.addContent(getMarkerAnchor("navbar_bottom_firstrow"));
   683             }
   684             HtmlTree navList = new HtmlTree(HtmlTag.UL);
   685             navList.addStyle(HtmlStyle.navList);
   686             navList.addAttr(HtmlAttr.TITLE, "Navigation");
   687             if (configuration.createoverview) {
   688                 navList.addContent(getNavLinkContents());
   689             }
   690             if (configuration.packages.length == 1) {
   691                 navList.addContent(getNavLinkPackage(configuration.packages[0]));
   692             } else if (configuration.packages.length > 1) {
   693                 navList.addContent(getNavLinkPackage());
   694             }
   695             navList.addContent(getNavLinkClass());
   696             if(configuration.classuse) {
   697                 navList.addContent(getNavLinkClassUse());
   698             }
   699             if(configuration.createtree) {
   700                 navList.addContent(getNavLinkTree());
   701             }
   702             if(!(configuration.nodeprecated ||
   703                      configuration.nodeprecatedlist)) {
   704                 navList.addContent(getNavLinkDeprecated());
   705             }
   706             if(configuration.createindex) {
   707                 navList.addContent(getNavLinkIndex());
   708             }
   709             if (!configuration.nohelp) {
   710                 navList.addContent(getNavLinkHelp());
   711             }
   712             navDiv.addContent(navList);
   713             Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header));
   714             navDiv.addContent(aboutDiv);
   715             body.addContent(navDiv);
   716             Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious());
   717             ulNav.addContent(getNavLinkNext());
   718             Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav);
   719             Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists());
   720             ulFrames.addContent(getNavHideLists(filename));
   721             subDiv.addContent(ulFrames);
   722             HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
   723             ulAllClasses.addAttr(HtmlAttr.ID, allClassesId.toString());
   724             subDiv.addContent(ulAllClasses);
   725             subDiv.addContent(getAllClassesLinkScript(allClassesId.toString()));
   726             addSummaryDetailLinks(subDiv);
   727             if (header) {
   728                 subDiv.addContent(getMarkerAnchor("skip-navbar_top"));
   729                 body.addContent(subDiv);
   730                 body.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
   731             } else {
   732                 subDiv.addContent(getMarkerAnchor("skip-navbar_bottom"));
   733                 body.addContent(subDiv);
   734                 body.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
   735             }
   736         }
   737     }
   739     /**
   740      * Print the word "NEXT" to indicate that no link is available.  Override
   741      * this method to customize next link.
   742      */
   743     protected void navLinkNext() {
   744         navLinkNext(null);
   745     }
   747     /**
   748      * Get the word "NEXT" to indicate that no link is available.  Override
   749      * this method to customize next link.
   750      *
   751      * @return a content tree for the link
   752      */
   753     protected Content getNavLinkNext() {
   754         return getNavLinkNext(null);
   755     }
   757     /**
   758      * Print the word "PREV" to indicate that no link is available.  Override
   759      * this method to customize prev link.
   760      */
   761     protected void navLinkPrevious() {
   762         navLinkPrevious(null);
   763     }
   765     /**
   766      * Get the word "PREV" to indicate that no link is available.  Override
   767      * this method to customize prev link.
   768      *
   769      * @return a content tree for the link
   770      */
   771     protected Content getNavLinkPrevious() {
   772         return getNavLinkPrevious(null);
   773     }
   775     /**
   776      * Do nothing. This is the default method.
   777      */
   778     protected void printSummaryDetailLinks() {
   779     }
   781     /**
   782      * Do nothing. This is the default method.
   783      */
   784     protected void addSummaryDetailLinks(Content navDiv) {
   785     }
   787     /**
   788      * Print link to the "overview-summary.html" page.
   789      */
   790     protected void navLinkContents() {
   791         navCellStart();
   792         printHyperLink(relativePath + "overview-summary.html", "",
   793                        configuration.getText("doclet.Overview"), true, "NavBarFont1");
   794         navCellEnd();
   795     }
   797     /**
   798      * Get link to the "overview-summary.html" page.
   799      *
   800      * @return a content tree for the link
   801      */
   802     protected Content getNavLinkContents() {
   803         Content linkContent = getHyperLink(relativePath +
   804                 "overview-summary.html", "", overviewLabel, "", "");
   805         Content li = HtmlTree.LI(linkContent);
   806         return li;
   807     }
   809     /**
   810      * Description for a cell in the navigation bar.
   811      */
   812     protected void navCellStart() {
   813         print("  ");
   814         tdBgcolorStyle("#EEEEFF", "NavBarCell1");
   815         print("    ");
   816     }
   818     /**
   819      * Description for a cell in the navigation bar, but with reverse
   820      * high-light effect.
   821      */
   822     protected void navCellRevStart() {
   823         print("  ");
   824         tdBgcolorStyle("#FFFFFF", "NavBarCell1Rev");
   825         print(" ");
   826         space();
   827     }
   829     /**
   830      * Closing tag for navigation bar cell.
   831      */
   832     protected void navCellEnd() {
   833         space();
   834         tdEnd();
   835     }
   837     /**
   838      * Print link to the "package-summary.html" page for the package passed.
   839      *
   840      * @param pkg Package to which link will be generated.
   841      */
   842     protected void navLinkPackage(PackageDoc pkg) {
   843         navCellStart();
   844         printPackageLink(pkg, configuration.getText("doclet.Package"), true,
   845             "NavBarFont1");
   846         navCellEnd();
   847     }
   849     /**
   850      * Get link to the "package-summary.html" page for the package passed.
   851      *
   852      * @param pkg Package to which link will be generated
   853      * @return a content tree for the link
   854      */
   855     protected Content getNavLinkPackage(PackageDoc pkg) {
   856         Content linkContent = getPackageLink(pkg,
   857                 packageLabel);
   858         Content li = HtmlTree.LI(linkContent);
   859         return li;
   860     }
   862     /**
   863      * Print the word "Package" in the navigation bar cell, to indicate that
   864      * link is not available here.
   865      */
   866     protected void navLinkPackage() {
   867         navCellStart();
   868         fontStyle("NavBarFont1");
   869         printText("doclet.Package");
   870         fontEnd();
   871         navCellEnd();
   872     }
   874     /**
   875      * Get the word "Package" , to indicate that link is not available here.
   876      *
   877      * @return a content tree for the link
   878      */
   879     protected Content getNavLinkPackage() {
   880         Content li = HtmlTree.LI(packageLabel);
   881         return li;
   882     }
   884     /**
   885      * Print the word "Use" in the navigation bar cell, to indicate that link
   886      * is not available.
   887      */
   888     protected void navLinkClassUse() {
   889         navCellStart();
   890         fontStyle("NavBarFont1");
   891         printText("doclet.navClassUse");
   892         fontEnd();
   893         navCellEnd();
   894     }
   896     /**
   897      * Get the word "Use", to indicate that link is not available.
   898      *
   899      * @return a content tree for the link
   900      */
   901     protected Content getNavLinkClassUse() {
   902         Content li = HtmlTree.LI(useLabel);
   903         return li;
   904     }
   906     /**
   907      * Print link for previous file.
   908      *
   909      * @param prev File name for the prev link.
   910      */
   911     public void navLinkPrevious(String prev) {
   912         String tag = configuration.getText("doclet.Prev");
   913         if (prev != null) {
   914             printHyperLink(prev, "", tag, true) ;
   915         } else {
   916             print(tag);
   917         }
   918     }
   920     /**
   921      * Get link for previous file.
   922      *
   923      * @param prev File name for the prev link
   924      * @return a content tree for the link
   925      */
   926     public Content getNavLinkPrevious(String prev) {
   927         Content li;
   928         if (prev != null) {
   929             li = HtmlTree.LI(getHyperLink(prev, "", prevLabel, "", ""));
   930         }
   931         else
   932             li = HtmlTree.LI(prevLabel);
   933         return li;
   934     }
   936     /**
   937      * Print link for next file.  If next is null, just print the label
   938      * without linking it anywhere.
   939      *
   940      * @param next File name for the next link.
   941      */
   942     public void navLinkNext(String next) {
   943         String tag = configuration.getText("doclet.Next");
   944         if (next != null) {
   945             printHyperLink(next, "", tag, true);
   946         } else {
   947             print(tag);
   948         }
   949     }
   951     /**
   952      * Get link for next file.  If next is null, just print the label
   953      * without linking it anywhere.
   954      *
   955      * @param next File name for the next link
   956      * @return a content tree for the link
   957      */
   958     public Content getNavLinkNext(String next) {
   959         Content li;
   960         if (next != null) {
   961             li = HtmlTree.LI(getHyperLink(next, "", nextLabel, "", ""));
   962         }
   963         else
   964             li = HtmlTree.LI(nextLabel);
   965         return li;
   966     }
   968     /**
   969      * Print "FRAMES" link, to switch to the frame version of the output.
   970      *
   971      * @param link File to be linked, "index.html".
   972      */
   973     protected void navShowLists(String link) {
   974         print(getHyperLinkString(link + "?" + path + filename, "",
   975             configuration.getText("doclet.FRAMES"), true, "", "", "_top"));
   976     }
   978     /**
   979      * Get "FRAMES" link, to switch to the frame version of the output.
   980      *
   981      * @param link File to be linked, "index.html"
   982      * @return a content tree for the link
   983      */
   984     protected Content getNavShowLists(String link) {
   985         Content framesContent = getHyperLink(link + "?" + path +
   986                 filename, "", framesLabel, "", "_top");
   987         Content li = HtmlTree.LI(framesContent);
   988         return li;
   989     }
   991     /**
   992      * Print "FRAMES" link, to switch to the frame version of the output.
   993      */
   994     protected void navShowLists() {
   995         navShowLists(relativePath + "index.html");
   996     }
   998     /**
   999      * Get "FRAMES" link, to switch to the frame version of the output.
  1001      * @return a content tree for the link
  1002      */
  1003     protected Content getNavShowLists() {
  1004         return getNavShowLists(relativePath + "index.html");
  1007     /**
  1008      * Print "NO FRAMES" link, to switch to the non-frame version of the output.
  1010      * @param link File to be linked.
  1011      */
  1012     protected void navHideLists(String link) {
  1013         print(getHyperLinkString(link, "", configuration.getText("doclet.NO_FRAMES"),
  1014             true, "", "", "_top"));
  1017     /**
  1018      * Get "NO FRAMES" link, to switch to the non-frame version of the output.
  1020      * @param link File to be linked
  1021      * @return a content tree for the link
  1022      */
  1023     protected Content getNavHideLists(String link) {
  1024         Content noFramesContent = getHyperLink(link, "", noframesLabel, "", "_top");
  1025         Content li = HtmlTree.LI(noFramesContent);
  1026         return li;
  1029     /**
  1030      * Print "Tree" link in the navigation bar. If there is only one package
  1031      * specified on the command line, then the "Tree" link will be to the
  1032      * only "package-tree.html" file otherwise it will be to the
  1033      * "overview-tree.html" file.
  1034      */
  1035     protected void navLinkTree() {
  1036         navCellStart();
  1037         PackageDoc[] packages = configuration.root.specifiedPackages();
  1038         if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) {
  1039             printHyperLink(pathString(packages[0], "package-tree.html"), "",
  1040                            configuration.getText("doclet.Tree"), true, "NavBarFont1");
  1041         } else {
  1042             printHyperLink(relativePath + "overview-tree.html", "",
  1043                            configuration.getText("doclet.Tree"), true, "NavBarFont1");
  1045         navCellEnd();
  1048     /**
  1049      * Get "Tree" link in the navigation bar. If there is only one package
  1050      * specified on the command line, then the "Tree" link will be to the
  1051      * only "package-tree.html" file otherwise it will be to the
  1052      * "overview-tree.html" file.
  1054      * @return a content tree for the link
  1055      */
  1056     protected Content getNavLinkTree() {
  1057         Content treeLinkContent;
  1058         PackageDoc[] packages = configuration.root.specifiedPackages();
  1059         if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) {
  1060             treeLinkContent = getHyperLink(pathString(packages[0],
  1061                     "package-tree.html"), "", treeLabel,
  1062                     "", "");
  1063         } else {
  1064             treeLinkContent = getHyperLink(relativePath + "overview-tree.html",
  1065                     "", treeLabel, "", "");
  1067         Content li = HtmlTree.LI(treeLinkContent);
  1068         return li;
  1071     /**
  1072      * Get the overview tree link for the main tree.
  1074      * @param label the label for the link
  1075      * @return a content tree for the link
  1076      */
  1077     protected Content getNavLinkMainTree(String label) {
  1078         Content mainTreeContent = getHyperLink(relativePath + "overview-tree.html",
  1079                 new StringContent(label));
  1080         Content li = HtmlTree.LI(mainTreeContent);
  1081         return li;
  1084     /**
  1085      * Print the word "Class" in the navigation bar cell, to indicate that
  1086      * class link is not available.
  1087      */
  1088     protected void navLinkClass() {
  1089         navCellStart();
  1090         fontStyle("NavBarFont1");
  1091         printText("doclet.Class");
  1092         fontEnd();
  1093         navCellEnd();
  1096     /**
  1097      * Get the word "Class", to indicate that class link is not available.
  1099      * @return a content tree for the link
  1100      */
  1101     protected Content getNavLinkClass() {
  1102         Content li = HtmlTree.LI(classLabel);
  1103         return li;
  1106     /**
  1107      * Print "Deprecated" API link in the navigation bar.
  1108      */
  1109     protected void navLinkDeprecated() {
  1110         navCellStart();
  1111         printHyperLink(relativePath + "deprecated-list.html", "",
  1112                        configuration.getText("doclet.navDeprecated"), true, "NavBarFont1");
  1113         navCellEnd();
  1116     /**
  1117      * Get "Deprecated" API link in the navigation bar.
  1119      * @return a content tree for the link
  1120      */
  1121     protected Content getNavLinkDeprecated() {
  1122         Content linkContent = getHyperLink(relativePath +
  1123                 "deprecated-list.html", "", deprecatedLabel, "", "");
  1124         Content li = HtmlTree.LI(linkContent);
  1125         return li;
  1128     /**
  1129      * Print link for generated index. If the user has used "-splitindex"
  1130      * command line option, then link to file "index-files/index-1.html" is
  1131      * generated otherwise link to file "index-all.html" is generated.
  1132      */
  1133     protected void navLinkClassIndex() {
  1134         printNoFramesTargetHyperLink(relativePath +
  1135                 AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES,
  1136             "", "", configuration.getText("doclet.All_Classes"), true);
  1139     /**
  1140      * Get link for generated index. If the user has used "-splitindex"
  1141      * command line option, then link to file "index-files/index-1.html" is
  1142      * generated otherwise link to file "index-all.html" is generated.
  1144      * @return a content tree for the link
  1145      */
  1146     protected Content getNavLinkClassIndex() {
  1147         Content allClassesContent = getHyperLink(relativePath +
  1148                 AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, "",
  1149                 allclassesLabel, "", "");
  1150         Content li = HtmlTree.LI(allClassesContent);
  1151         return li;
  1153     /**
  1154      * Print link for generated class index.
  1155      */
  1156     protected void navLinkIndex() {
  1157         navCellStart();
  1158         printHyperLink(relativePath +
  1159                            (configuration.splitindex?
  1160                                 DirectoryManager.getPath("index-files") +
  1161                                 fileseparator: "") +
  1162                            (configuration.splitindex?
  1163                                 "index-1.html" : "index-all.html"), "",
  1164                        configuration.getText("doclet.Index"), true, "NavBarFont1");
  1165         navCellEnd();
  1168     /**
  1169      * Get link for generated class index.
  1171      * @return a content tree for the link
  1172      */
  1173     protected Content getNavLinkIndex() {
  1174         Content linkContent = getHyperLink(relativePath +(configuration.splitindex?
  1175             DirectoryManager.getPath("index-files") + fileseparator: "") +
  1176             (configuration.splitindex?"index-1.html" : "index-all.html"), "",
  1177             indexLabel, "", "");
  1178         Content li = HtmlTree.LI(linkContent);
  1179         return li;
  1182     /**
  1183      * Print help file link. If user has provided a help file, then generate a
  1184      * link to the user given file, which is already copied to current or
  1185      * destination directory.
  1186      */
  1187     protected void navLinkHelp() {
  1188         String helpfilenm = configuration.helpfile;
  1189         if (helpfilenm.equals("")) {
  1190             helpfilenm = "help-doc.html";
  1191         } else {
  1192             int lastsep;
  1193             if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) {
  1194                 helpfilenm = helpfilenm.substring(lastsep + 1);
  1197         navCellStart();
  1198         printHyperLink(relativePath + helpfilenm, "",
  1199                        configuration.getText("doclet.Help"), true, "NavBarFont1");
  1200         navCellEnd();
  1203     /**
  1204      * Get help file link. If user has provided a help file, then generate a
  1205      * link to the user given file, which is already copied to current or
  1206      * destination directory.
  1208      * @return a content tree for the link
  1209      */
  1210     protected Content getNavLinkHelp() {
  1211         String helpfilenm = configuration.helpfile;
  1212         if (helpfilenm.equals("")) {
  1213             helpfilenm = "help-doc.html";
  1214         } else {
  1215             int lastsep;
  1216             if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) {
  1217                 helpfilenm = helpfilenm.substring(lastsep + 1);
  1220         Content linkContent = getHyperLink(relativePath + helpfilenm, "",
  1221                 helpLabel, "", "");
  1222         Content li = HtmlTree.LI(linkContent);
  1223         return li;
  1226     /**
  1227      * Print the word "Detail" in the navigation bar. No link is available.
  1228      */
  1229     protected void navDetail() {
  1230         printText("doclet.Detail");
  1233     /**
  1234      * Print the word "Summary" in the navigation bar. No link is available.
  1235      */
  1236     protected void navSummary() {
  1237         printText("doclet.Summary");
  1240     /**
  1241      * Print the Html table tag for the index summary tables. The table tag
  1242      * printed is
  1243      * &lt;TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
  1244      */
  1245     public void tableIndexSummary() {
  1246         table(1, "100%", 3, 0);
  1249     /**
  1250      * Print the Html table tag for the index summary tables.
  1252      * @param summary the summary for the table tag summary attribute.
  1253      */
  1254     public void tableIndexSummary(String summary) {
  1255         table(1, "100%", 3, 0, summary);
  1258     /**
  1259      * Same as {@link #tableIndexSummary()}.
  1260      */
  1261     public void tableIndexDetail() {
  1262         table(1, "100%", 3, 0);
  1265     /**
  1266      * Print Html tag for table elements. The tag printed is
  1267      * &lt;TD ALIGN="right" VALIGN="top" WIDTH="1%"&gt;.
  1268      */
  1269     public void tdIndex() {
  1270         print("<TD ALIGN=\"right\" VALIGN=\"top\" WIDTH=\"1%\">");
  1273     /**
  1274      * Print table caption.
  1275      */
  1276     public void tableCaptionStart() {
  1277         captionStyle("TableCaption");
  1280     /**
  1281      * Print table sub-caption.
  1282      */
  1283     public void tableSubCaptionStart() {
  1284         captionStyle("TableSubCaption");
  1287     /**
  1288      * Print table caption end tags.
  1289      */
  1290     public void tableCaptionEnd() {
  1291         captionEnd();
  1294     /**
  1295      * Print summary table header.
  1296      */
  1297     public void summaryTableHeader(String[] header, String scope) {
  1298         tr();
  1299         for ( int i=0; i < header.length; i++ ) {
  1300             thScopeNoWrap("TableHeader", scope);
  1301             print(header[i]);
  1302             thEnd();
  1304         trEnd();
  1307     /**
  1308      * Get summary table header.
  1310      * @param header the header for the table
  1311      * @param scope the scope of the headers
  1312      * @return a content tree for the header
  1313      */
  1314     public Content getSummaryTableHeader(String[] header, String scope) {
  1315         Content tr = new HtmlTree(HtmlTag.TR);
  1316         int size = header.length;
  1317         Content tableHeader;
  1318         if (size == 1) {
  1319             tableHeader = new StringContent(header[0]);
  1320             tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader));
  1321             return tr;
  1323         for (int i = 0; i < size; i++) {
  1324             tableHeader = new StringContent(header[i]);
  1325             if(i == 0)
  1326                 tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
  1327             else if(i == (size - 1))
  1328                 tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
  1329             else
  1330                 tr.addContent(HtmlTree.TH(scope, tableHeader));
  1332         return tr;
  1335     /**
  1336      * Get table caption.
  1338      * @param rawText the caption for the table which could be raw Html
  1339      * @return a content tree for the caption
  1340      */
  1341     public Content getTableCaption(String rawText) {
  1342         Content title = new RawHtml(rawText);
  1343         Content captionSpan = HtmlTree.SPAN(title);
  1344         Content space = getSpace();
  1345         Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
  1346         Content caption = HtmlTree.CAPTION(captionSpan);
  1347         caption.addContent(tabSpan);
  1348         return caption;
  1351     /**
  1352      * Get the marker anchor which will be added to the documentation tree.
  1354      * @param anchorName the anchor name attribute
  1355      * @return a content tree for the marker anchor
  1356      */
  1357     public Content getMarkerAnchor(String anchorName) {
  1358         return getMarkerAnchor(anchorName, null);
  1361     /**
  1362      * Get the marker anchor which will be added to the documentation tree.
  1364      * @param anchorName the anchor name attribute
  1365      * @param anchorContent the content that should be added to the anchor
  1366      * @return a content tree for the marker anchor
  1367      */
  1368     public Content getMarkerAnchor(String anchorName, Content anchorContent) {
  1369         if (anchorContent == null)
  1370             anchorContent = new Comment(" ");
  1371         Content markerAnchor = HtmlTree.A_NAME(anchorName, anchorContent);
  1372         return markerAnchor;
  1375     /**
  1376      * Returns a packagename content.
  1378      * @param packageDoc the package to check
  1379      * @return package name content
  1380      */
  1381     public Content getPackageName(PackageDoc packageDoc) {
  1382         return packageDoc == null || packageDoc.name().length() == 0 ?
  1383             defaultPackageLabel :
  1384             getPackageLabel(packageDoc.name());
  1387     /**
  1388      * Returns a package name label.
  1390      * @param parsedName the package name
  1391      * @return the package name content
  1392      */
  1393     public Content getPackageLabel(String packageName) {
  1394         return new StringContent(packageName);
  1397     /**
  1398      * Prine table header information about color, column span and the font.
  1400      * @param color Background color.
  1401      * @param span  Column span.
  1402      */
  1403     public void tableHeaderStart(String color, int span) {
  1404         trBgcolorStyle(color, "TableHeadingColor");
  1405         thAlignColspan("left", span);
  1406         font("+2");
  1409     /**
  1410      * Print table header for the inherited members summary tables. Print the
  1411      * background color information.
  1413      * @param color Background color.
  1414      */
  1415     public void tableInheritedHeaderStart(String color) {
  1416         trBgcolorStyle(color, "TableSubHeadingColor");
  1417         thAlign("left");
  1420     /**
  1421      * Print "Use" table header. Print the background color and the column span.
  1423      * @param color Background color.
  1424      */
  1425     public void tableUseInfoHeaderStart(String color) {
  1426         trBgcolorStyle(color, "TableSubHeadingColor");
  1427         thAlignColspan("left", 2);
  1430     /**
  1431      * Print table header with the background color with default column span 2.
  1433      * @param color Background color.
  1434      */
  1435     public void tableHeaderStart(String color) {
  1436         tableHeaderStart(color, 2);
  1439     /**
  1440      * Print table header with the column span, with the default color #CCCCFF.
  1442      * @param span Column span.
  1443      */
  1444     public void tableHeaderStart(int span) {
  1445         tableHeaderStart("#CCCCFF", span);
  1448     /**
  1449      * Print table header with default column span 2 and default color #CCCCFF.
  1450      */
  1451     public void tableHeaderStart() {
  1452         tableHeaderStart(2);
  1455     /**
  1456      * Print table header end tags for font, column and row.
  1457      */
  1458     public void tableHeaderEnd() {
  1459         fontEnd();
  1460         thEnd();
  1461         trEnd();
  1464     /**
  1465      * Print table header end tags in inherited tables for column and row.
  1466      */
  1467     public void tableInheritedHeaderEnd() {
  1468         thEnd();
  1469         trEnd();
  1472     /**
  1473      * Print the summary table row cell attribute width.
  1475      * @param width Width of the table cell.
  1476      */
  1477     public void summaryRow(int width) {
  1478         if (width != 0) {
  1479             tdWidth(width + "%");
  1480         } else {
  1481             td();
  1485     /**
  1486      * Print the summary table row cell end tag.
  1487      */
  1488     public void summaryRowEnd() {
  1489         tdEnd();
  1492     /**
  1493      * Print the heading in Html &lt;H2> format.
  1495      * @param str The Header string.
  1496      */
  1497     public void printIndexHeading(String str) {
  1498         h2();
  1499         print(str);
  1500         h2End();
  1503     /**
  1504      * Print Html tag &lt;FRAMESET=arg&gt;.
  1506      * @param arg Argument for the tag.
  1507      */
  1508     public void frameSet(String arg) {
  1509         println("<FRAMESET " + arg + ">");
  1512     /**
  1513      * Print Html closing tag &lt;/FRAMESET&gt;.
  1514      */
  1515     public void frameSetEnd() {
  1516         println("</FRAMESET>");
  1519     /**
  1520      * Print Html tag &lt;FRAME=arg&gt;.
  1522      * @param arg Argument for the tag.
  1523      */
  1524     public void frame(String arg) {
  1525         println("<FRAME " + arg + ">");
  1528     /**
  1529      * Print Html closing tag &lt;/FRAME&gt;.
  1530      */
  1531     public void frameEnd() {
  1532         println("</FRAME>");
  1535     /**
  1536      * Return path to the class page for a classdoc. For example, the class
  1537      * name is "java.lang.Object" and if the current file getting generated is
  1538      * "java/io/File.html", then the path string to the class, returned is
  1539      * "../../java/lang.Object.html".
  1541      * @param cd Class to which the path is requested.
  1542      */
  1543     protected String pathToClass(ClassDoc cd) {
  1544         return pathString(cd.containingPackage(), cd.name() + ".html");
  1547     /**
  1548      * Return the path to the class page for a classdoc. Works same as
  1549      * {@link #pathToClass(ClassDoc)}.
  1551      * @param cd   Class to which the path is requested.
  1552      * @param name Name of the file(doesn't include path).
  1553      */
  1554     protected String pathString(ClassDoc cd, String name) {
  1555         return pathString(cd.containingPackage(), name);
  1558     /**
  1559      * Return path to the given file name in the given package. So if the name
  1560      * passed is "Object.html" and the name of the package is "java.lang", and
  1561      * if the relative path is "../.." then returned string will be
  1562      * "../../java/lang/Object.html"
  1564      * @param pd Package in which the file name is assumed to be.
  1565      * @param name File name, to which path string is.
  1566      */
  1567     protected String pathString(PackageDoc pd, String name) {
  1568         StringBuffer buf = new StringBuffer(relativePath);
  1569         buf.append(DirectoryManager.getPathToPackage(pd, name));
  1570         return buf.toString();
  1573     /**
  1574      * Print the link to the given package.
  1576      * @param pkg the package to link to.
  1577      * @param label the label for the link.
  1578      * @param isStrong true if the label should be strong.
  1579      */
  1580     public void printPackageLink(PackageDoc pkg, String label, boolean isStrong) {
  1581         print(getPackageLinkString(pkg, label, isStrong));
  1584     /**
  1585      * Print the link to the given package.
  1587      * @param pkg the package to link to.
  1588      * @param label the label for the link.
  1589      * @param isStrong true if the label should be strong.
  1590      * @param style  the font of the package link label.
  1591      */
  1592     public void printPackageLink(PackageDoc pkg, String label, boolean isStrong,
  1593             String style) {
  1594         print(getPackageLinkString(pkg, label, isStrong, style));
  1597     /**
  1598      * Return the link to the given package.
  1600      * @param pkg the package to link to.
  1601      * @param label the label for the link.
  1602      * @param isStrong true if the label should be strong.
  1603      * @return the link to the given package.
  1604      */
  1605     public String getPackageLinkString(PackageDoc pkg, String label,
  1606                                  boolean isStrong) {
  1607         return getPackageLinkString(pkg, label, isStrong, "");
  1610     /**
  1611      * Return the link to the given package.
  1613      * @param pkg the package to link to.
  1614      * @param label the label for the link.
  1615      * @param isStrong true if the label should be strong.
  1616      * @param style  the font of the package link label.
  1617      * @return the link to the given package.
  1618      */
  1619     public String getPackageLinkString(PackageDoc pkg, String label, boolean isStrong,
  1620             String style) {
  1621         boolean included = pkg != null && pkg.isIncluded();
  1622         if (! included) {
  1623             PackageDoc[] packages = configuration.packages;
  1624             for (int i = 0; i < packages.length; i++) {
  1625                 if (packages[i].equals(pkg)) {
  1626                     included = true;
  1627                     break;
  1631         if (included || pkg == null) {
  1632             return getHyperLinkString(pathString(pkg, "package-summary.html"),
  1633                                 "", label, isStrong, style);
  1634         } else {
  1635             String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
  1636             if (crossPkgLink != null) {
  1637                 return getHyperLinkString(crossPkgLink, "", label, isStrong, style);
  1638             } else {
  1639                 return label;
  1644     /**
  1645      * Return the link to the given package.
  1647      * @param pkg the package to link to.
  1648      * @param label the label for the link.
  1649      * @return a content tree for the package link.
  1650      */
  1651     public Content getPackageLink(PackageDoc pkg, Content label) {
  1652         boolean included = pkg != null && pkg.isIncluded();
  1653         if (! included) {
  1654             PackageDoc[] packages = configuration.packages;
  1655             for (int i = 0; i < packages.length; i++) {
  1656                 if (packages[i].equals(pkg)) {
  1657                     included = true;
  1658                     break;
  1662         if (included || pkg == null) {
  1663             return getHyperLink(pathString(pkg, "package-summary.html"),
  1664                                 "", label);
  1665         } else {
  1666             String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
  1667             if (crossPkgLink != null) {
  1668                 return getHyperLink(crossPkgLink, "", label);
  1669             } else {
  1670                 return label;
  1675     public String italicsClassName(ClassDoc cd, boolean qual) {
  1676         String name = (qual)? cd.qualifiedName(): cd.name();
  1677         return (cd.isInterface())?  italicsText(name): name;
  1680     public void printSrcLink(ProgramElementDoc d, String label) {
  1681         if (d == null) {
  1682             return;
  1684         ClassDoc cd = d.containingClass();
  1685         if (cd == null) {
  1686             //d must be a class doc since in has no containing class.
  1687             cd = (ClassDoc) d;
  1689         String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
  1690             + DirectoryManager.getDirectoryPath(cd.containingPackage())
  1691             + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(d);
  1692         printHyperLink(href, "", label, true);
  1695     /**
  1696      * Add the link to the content tree.
  1698      * @param doc program element doc for which the link will be added
  1699      * @param label label for the link
  1700      * @param htmltree the content tree to which the link will be added
  1701      */
  1702     public void addSrcLink(ProgramElementDoc doc, Content label, Content htmltree) {
  1703         if (doc == null) {
  1704             return;
  1706         ClassDoc cd = doc.containingClass();
  1707         if (cd == null) {
  1708             //d must be a class doc since in has no containing class.
  1709             cd = (ClassDoc) doc;
  1711         String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
  1712                 + DirectoryManager.getDirectoryPath(cd.containingPackage())
  1713                 + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(doc);
  1714         Content linkContent = getHyperLink(href, "", label, "", "");
  1715         htmltree.addContent(linkContent);
  1718     /**
  1719      * Return the link to the given class.
  1721      * @param linkInfo the information about the link.
  1723      * @return the link for the given class.
  1724      */
  1725     public String getLink(LinkInfoImpl linkInfo) {
  1726         LinkFactoryImpl factory = new LinkFactoryImpl(this);
  1727         String link = ((LinkOutputImpl) factory.getLinkOutput(linkInfo)).toString();
  1728         displayLength += linkInfo.displayLength;
  1729         return link;
  1732     /**
  1733      * Return the type parameters for the given class.
  1735      * @param linkInfo the information about the link.
  1736      * @return the type for the given class.
  1737      */
  1738     public String getTypeParameterLinks(LinkInfoImpl linkInfo) {
  1739         LinkFactoryImpl factory = new LinkFactoryImpl(this);
  1740         return ((LinkOutputImpl)
  1741             factory.getTypeParameterLinks(linkInfo, false)).toString();
  1744     /**
  1745      * Print the link to the given class.
  1746      */
  1747     public void printLink(LinkInfoImpl linkInfo) {
  1748         print(getLink(linkInfo));
  1751     /*************************************************************
  1752      * Return a class cross link to external class documentation.
  1753      * The name must be fully qualified to determine which package
  1754      * the class is in.  The -link option does not allow users to
  1755      * link to external classes in the "default" package.
  1757      * @param qualifiedClassName the qualified name of the external class.
  1758      * @param refMemName the name of the member being referenced.  This should
  1759      * be null or empty string if no member is being referenced.
  1760      * @param label the label for the external link.
  1761      * @param strong true if the link should be strong.
  1762      * @param style the style of the link.
  1763      * @param code true if the label should be code font.
  1764      */
  1765     public String getCrossClassLink(String qualifiedClassName, String refMemName,
  1766                                     String label, boolean strong, String style,
  1767                                     boolean code) {
  1768         String className = "",
  1769             packageName = qualifiedClassName == null ? "" : qualifiedClassName;
  1770         int periodIndex;
  1771         while((periodIndex = packageName.lastIndexOf('.')) != -1) {
  1772             className = packageName.substring(periodIndex + 1, packageName.length()) +
  1773                 (className.length() > 0 ? "." + className : "");
  1774             String defaultLabel = code ? getCode() + className + getCodeEnd() : className;
  1775             packageName = packageName.substring(0, periodIndex);
  1776             if (getCrossPackageLink(packageName) != null) {
  1777                 //The package exists in external documentation, so link to the external
  1778                 //class (assuming that it exists).  This is definitely a limitation of
  1779                 //the -link option.  There are ways to determine if an external package
  1780                 //exists, but no way to determine if the external class exists.  We just
  1781                 //have to assume that it does.
  1782                 return getHyperLinkString(
  1783                     configuration.extern.getExternalLink(packageName, relativePath,
  1784                                 className + ".html?is-external=true"),
  1785                     refMemName == null ? "" : refMemName,
  1786                     label == null || label.length() == 0 ? defaultLabel : label,
  1787                     strong, style,
  1788                     configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
  1789                     "");
  1792         return null;
  1795     public boolean isClassLinkable(ClassDoc cd) {
  1796         if (cd.isIncluded()) {
  1797             return configuration.isGeneratedDoc(cd);
  1799         return configuration.extern.isExternal(cd);
  1802     public String getCrossPackageLink(String pkgName) {
  1803         return configuration.extern.getExternalLink(pkgName, relativePath,
  1804             "package-summary.html?is-external=true");
  1807     /**
  1808      * Get the class link.
  1810      * @param context the id of the context where the link will be added
  1811      * @param cd the class doc to link to
  1812      * @return a content tree for the link
  1813      */
  1814     public Content getQualifiedClassLink(int context, ClassDoc cd) {
  1815         return new RawHtml(getLink(new LinkInfoImpl(context, cd,
  1816                 configuration.getClassName(cd), "")));
  1819     /**
  1820      * Add the class link.
  1822      * @param context the id of the context where the link will be added
  1823      * @param cd the class doc to link to
  1824      * @param contentTree the content tree to which the link will be added
  1825      */
  1826     public void addPreQualifiedClassLink(int context, ClassDoc cd, Content contentTree) {
  1827         addPreQualifiedClassLink(context, cd, false, contentTree);
  1830     /**
  1831      * Retrieve the class link with the package portion of the label in
  1832      * plain text.  If the qualifier is excluded, it willnot be included in the
  1833      * link label.
  1835      * @param cd the class to link to.
  1836      * @param isStrong true if the link should be strong.
  1837      * @return the link with the package portion of the label in plain text.
  1838      */
  1839     public String getPreQualifiedClassLink(int context,
  1840             ClassDoc cd, boolean isStrong) {
  1841         String classlink = "";
  1842         PackageDoc pd = cd.containingPackage();
  1843         if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
  1844             classlink = getPkgName(cd);
  1846         classlink += getLink(new LinkInfoImpl(context, cd, cd.name(), isStrong));
  1847         return classlink;
  1850     /**
  1851      * Add the class link with the package portion of the label in
  1852      * plain text. If the qualifier is excluded, it will not be included in the
  1853      * link label.
  1855      * @param context the id of the context where the link will be added
  1856      * @param cd the class to link to
  1857      * @param isStrong true if the link should be strong
  1858      * @param contentTree the content tree to which the link with be added
  1859      */
  1860     public void addPreQualifiedClassLink(int context,
  1861             ClassDoc cd, boolean isStrong, Content contentTree) {
  1862         PackageDoc pd = cd.containingPackage();
  1863         if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
  1864             contentTree.addContent(getPkgName(cd));
  1866         contentTree.addContent(new RawHtml(getLink(new LinkInfoImpl(
  1867                 context, cd, cd.name(), isStrong))));
  1870     /**
  1871      * Add the class link, with only class name as the strong link and prefixing
  1872      * plain package name.
  1874      * @param context the id of the context where the link will be added
  1875      * @param cd the class to link to
  1876      * @param contentTree the content tree to which the link with be added
  1877      */
  1878     public void addPreQualifiedStrongClassLink(int context, ClassDoc cd, Content contentTree) {
  1879         addPreQualifiedClassLink(context, cd, true, contentTree);
  1882     public void printText(String key) {
  1883         print(configuration.getText(key));
  1886     public void printText(String key, String a1) {
  1887         print(configuration.getText(key, a1));
  1890     public void printText(String key, String a1, String a2) {
  1891         print(configuration.getText(key, a1, a2));
  1894     public void strongText(String key) {
  1895         strong(configuration.getText(key));
  1898     public void strongText(String key, String a1) {
  1899         strong(configuration.getText(key, a1));
  1902     public void strongText(String key, String a1, String a2) {
  1903         strong(configuration.getText(key, a1, a2));
  1906     /**
  1907      * Get the link for the given member.
  1909      * @param context the id of the context where the link will be added
  1910      * @param doc the member being linked to
  1911      * @param label the label for the link
  1912      * @return a content tree for the doc link
  1913      */
  1914     public Content getDocLink(int context, MemberDoc doc, String label) {
  1915         return getDocLink(context, doc.containingClass(), doc, label);
  1918     /**
  1919      * Print the link for the given member.
  1921      * @param context the id of the context where the link will be printed.
  1922      * @param classDoc the classDoc that we should link to.  This is not
  1923      *                 necessarily equal to doc.containingClass().  We may be
  1924      *                 inheriting comments.
  1925      * @param doc the member being linked to.
  1926      * @param label the label for the link.
  1927      * @param strong true if the link should be strong.
  1928      */
  1929     public void printDocLink(int context, ClassDoc classDoc, MemberDoc doc,
  1930             String label, boolean strong) {
  1931         print(getDocLink(context, classDoc, doc, label, strong));
  1934     /**
  1935      * Return the link for the given member.
  1937      * @param context the id of the context where the link will be printed.
  1938      * @param doc the member being linked to.
  1939      * @param label the label for the link.
  1940      * @param strong true if the link should be strong.
  1941      * @return the link for the given member.
  1942      */
  1943     public String getDocLink(int context, MemberDoc doc, String label,
  1944                 boolean strong) {
  1945         return getDocLink(context, doc.containingClass(), doc, label, strong);
  1948     /**
  1949      * Return the link for the given member.
  1951      * @param context the id of the context where the link will be printed.
  1952      * @param classDoc the classDoc that we should link to.  This is not
  1953      *                 necessarily equal to doc.containingClass().  We may be
  1954      *                 inheriting comments.
  1955      * @param doc the member being linked to.
  1956      * @param label the label for the link.
  1957      * @param strong true if the link should be strong.
  1958      * @return the link for the given member.
  1959      */
  1960     public String getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
  1961         String label, boolean strong) {
  1962         if (! (doc.isIncluded() ||
  1963             Util.isLinkable(classDoc, configuration()))) {
  1964             return label;
  1965         } else if (doc instanceof ExecutableMemberDoc) {
  1966             ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
  1967             return getLink(new LinkInfoImpl(context, classDoc,
  1968                 getAnchor(emd), label, strong));
  1969         } else if (doc instanceof MemberDoc) {
  1970             return getLink(new LinkInfoImpl(context, classDoc,
  1971                 doc.name(), label, strong));
  1972         } else {
  1973             return label;
  1977     /**
  1978      * Return the link for the given member.
  1980      * @param context the id of the context where the link will be added
  1981      * @param classDoc the classDoc that we should link to.  This is not
  1982      *                 necessarily equal to doc.containingClass().  We may be
  1983      *                 inheriting comments
  1984      * @param doc the member being linked to
  1985      * @param label the label for the link
  1986      * @return the link for the given member
  1987      */
  1988     public Content getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
  1989         String label) {
  1990         if (! (doc.isIncluded() ||
  1991             Util.isLinkable(classDoc, configuration()))) {
  1992             return new StringContent(label);
  1993         } else if (doc instanceof ExecutableMemberDoc) {
  1994             ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
  1995             return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
  1996                 getAnchor(emd), label, false)));
  1997         } else if (doc instanceof MemberDoc) {
  1998             return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
  1999                 doc.name(), label, false)));
  2000         } else {
  2001             return new StringContent(label);
  2005     public void anchor(ExecutableMemberDoc emd) {
  2006         anchor(getAnchor(emd));
  2009     public String getAnchor(ExecutableMemberDoc emd) {
  2010         StringBuilder signature = new StringBuilder(emd.signature());
  2011         StringBuilder signatureParsed = new StringBuilder();
  2012         int counter = 0;
  2013         for (int i = 0; i < signature.length(); i++) {
  2014             char c = signature.charAt(i);
  2015             if (c == '<') {
  2016                 counter++;
  2017             } else if (c == '>') {
  2018                 counter--;
  2019             } else if (counter == 0) {
  2020                 signatureParsed.append(c);
  2023         return emd.name() + signatureParsed.toString();
  2026     public String seeTagToString(SeeTag see) {
  2027         String tagName = see.name();
  2028         if (! (tagName.startsWith("@link") || tagName.equals("@see"))) {
  2029             return "";
  2031         StringBuffer result = new StringBuffer();
  2032         boolean isplaintext = tagName.toLowerCase().equals("@linkplain");
  2033         String label = see.label();
  2034         label = (label.length() > 0)?
  2035             ((isplaintext) ? label :
  2036                  getCode() + label + getCodeEnd()):"";
  2037         String seetext = replaceDocRootDir(see.text());
  2039         //Check if @see is an href or "string"
  2040         if (seetext.startsWith("<") || seetext.startsWith("\"")) {
  2041             result.append(seetext);
  2042             return result.toString();
  2045         //The text from the @see tag.  We will output this text when a label is not specified.
  2046         String text = (isplaintext) ? seetext : getCode() + seetext + getCodeEnd();
  2048         ClassDoc refClass = see.referencedClass();
  2049         String refClassName = see.referencedClassName();
  2050         MemberDoc refMem = see.referencedMember();
  2051         String refMemName = see.referencedMemberName();
  2052         if (refClass == null) {
  2053             //@see is not referencing an included class
  2054             PackageDoc refPackage = see.referencedPackage();
  2055             if (refPackage != null && refPackage.isIncluded()) {
  2056                 //@see is referencing an included package
  2057                 String packageName = isplaintext ? refPackage.name() :
  2058                     getCode() + refPackage.name() + getCodeEnd();
  2059                 result.append(getPackageLinkString(refPackage,
  2060                     label.length() == 0 ? packageName : label, false));
  2061             } else {
  2062                 //@see is not referencing an included class or package.  Check for cross links.
  2063                 String classCrossLink, packageCrossLink = getCrossPackageLink(refClassName);
  2064                 if (packageCrossLink != null) {
  2065                     //Package cross link found
  2066                     result.append(getHyperLinkString(packageCrossLink, "",
  2067                         (label.length() == 0)? text : label, false));
  2068                 } else if ((classCrossLink = getCrossClassLink(refClassName,
  2069                         refMemName, label, false, "", ! isplaintext)) != null) {
  2070                     //Class cross link found (possiblly to a member in the class)
  2071                     result.append(classCrossLink);
  2072                 } else {
  2073                     //No cross link found so print warning
  2074                     configuration.getDocletSpecificMsg().warning(see.position(), "doclet.see.class_or_package_not_found",
  2075                             tagName, seetext);
  2076                     result.append((label.length() == 0)? text: label);
  2079         } else if (refMemName == null) {
  2080             // Must be a class reference since refClass is not null and refMemName is null.
  2081             if (label.length() == 0) {
  2082                 label = (isplaintext) ? refClass.name() : getCode() + refClass.name() + getCodeEnd();
  2083                 result.append(getLink(new LinkInfoImpl(refClass, label)));
  2084             } else {
  2085                 result.append(getLink(new LinkInfoImpl(refClass, label)));
  2087         } else if (refMem == null) {
  2088             // Must be a member reference since refClass is not null and refMemName is not null.
  2089             // However, refMem is null, so this referenced member does not exist.
  2090             result.append((label.length() == 0)? text: label);
  2091         } else {
  2092             // Must be a member reference since refClass is not null and refMemName is not null.
  2093             // refMem is not null, so this @see tag must be referencing a valid member.
  2094             ClassDoc containing = refMem.containingClass();
  2095             if (see.text().trim().startsWith("#") &&
  2096                 ! (containing.isPublic() ||
  2097                 Util.isLinkable(containing, configuration()))) {
  2098                 // Since the link is relative and the holder is not even being
  2099                 // documented, this must be an inherited link.  Redirect it.
  2100                 // The current class either overrides the referenced member or
  2101                 // inherits it automatically.
  2102                 if (this instanceof ClassWriterImpl) {
  2103                     containing = ((ClassWriterImpl) this).getClassDoc();
  2104                 } else if (!containing.isPublic()){
  2105                     configuration.getDocletSpecificMsg().warning(
  2106                         see.position(), "doclet.see.class_or_package_not_accessible",
  2107                         tagName, containing.qualifiedName());
  2108                 } else {
  2109                     configuration.getDocletSpecificMsg().warning(
  2110                         see.position(), "doclet.see.class_or_package_not_found",
  2111                         tagName, seetext);
  2114             if (configuration.currentcd != containing) {
  2115                 refMemName = containing.name() + "." + refMemName;
  2117             if (refMem instanceof ExecutableMemberDoc) {
  2118                 if (refMemName.indexOf('(') < 0) {
  2119                     refMemName += ((ExecutableMemberDoc)refMem).signature();
  2122             text = (isplaintext) ?
  2123                 refMemName : getCode() + Util.escapeHtmlChars(refMemName) + getCodeEnd();
  2125             result.append(getDocLink(LinkInfoImpl.CONTEXT_SEE_TAG, containing,
  2126                 refMem, (label.length() == 0)? text: label, false));
  2128         return result.toString();
  2131     public void printInlineComment(Doc doc, Tag tag) {
  2132         printCommentTags(doc, tag.inlineTags(), false, false);
  2135     /**
  2136      * Add the inline comment.
  2138      * @param doc the doc for which the inline comment will be added
  2139      * @param tag the inline tag to be added
  2140      * @param htmltree the content tree to which the comment will be added
  2141      */
  2142     public void addInlineComment(Doc doc, Tag tag, Content htmltree) {
  2143         addCommentTags(doc, tag.inlineTags(), false, false, htmltree);
  2146     public void printInlineDeprecatedComment(Doc doc, Tag tag) {
  2147         printCommentTags(doc, tag.inlineTags(), true, false);
  2150     /**
  2151      * Add the inline deprecated comment.
  2153      * @param doc the doc for which the inline deprecated comment will be added
  2154      * @param tag the inline tag to be added
  2155      * @param htmltree the content tree to which the comment will be added
  2156      */
  2157     public void addInlineDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
  2158         addCommentTags(doc, tag.inlineTags(), true, false, htmltree);
  2161     public void printSummaryComment(Doc doc) {
  2162         printSummaryComment(doc, doc.firstSentenceTags());
  2165     /**
  2166      * Adds the summary content.
  2168      * @param doc the doc for which the summary will be generated
  2169      * @param htmltree the documentation tree to which the summary will be added
  2170      */
  2171     public void addSummaryComment(Doc doc, Content htmltree) {
  2172         addSummaryComment(doc, doc.firstSentenceTags(), htmltree);
  2175     public void printSummaryComment(Doc doc, Tag[] firstSentenceTags) {
  2176         printCommentTags(doc, firstSentenceTags, false, true);
  2179     /**
  2180      * Adds the summary content.
  2182      * @param doc the doc for which the summary will be generated
  2183      * @param firstSentenceTags the first sentence tags for the doc
  2184      * @param htmltree the documentation tree to which the summary will be added
  2185      */
  2186     public void addSummaryComment(Doc doc, Tag[] firstSentenceTags, Content htmltree) {
  2187         addCommentTags(doc, firstSentenceTags, false, true, htmltree);
  2190     public void printSummaryDeprecatedComment(Doc doc) {
  2191         printCommentTags(doc, doc.firstSentenceTags(), true, true);
  2194     public void printSummaryDeprecatedComment(Doc doc, Tag tag) {
  2195         printCommentTags(doc, tag.firstSentenceTags(), true, true);
  2198     public void addSummaryDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
  2199         addCommentTags(doc, tag.firstSentenceTags(), true, true, htmltree);
  2202     public void printInlineComment(Doc doc) {
  2203         printCommentTags(doc, doc.inlineTags(), false, false);
  2204         p();
  2207     /**
  2208      * Adds the inline comment.
  2210      * @param doc the doc for which the inline comments will be generated
  2211      * @param htmltree the documentation tree to which the inline comments will be added
  2212      */
  2213     public void addInlineComment(Doc doc, Content htmltree) {
  2214         addCommentTags(doc, doc.inlineTags(), false, false, htmltree);
  2217     public void printInlineDeprecatedComment(Doc doc) {
  2218         printCommentTags(doc, doc.inlineTags(), true, false);
  2221     private void printCommentTags(Doc doc, Tag[] tags, boolean depr, boolean first) {
  2222         if(configuration.nocomment){
  2223             return;
  2225         if (depr) {
  2226             italic();
  2228         String result = commentTagsToString(null, doc, tags, first);
  2229         print(result);
  2230         if (depr) {
  2231             italicEnd();
  2233         if (tags.length == 0) {
  2234             space();
  2238     /**
  2239      * Adds the comment tags.
  2241      * @param doc the doc for which the comment tags will be generated
  2242      * @param tags the first sentence tags for the doc
  2243      * @param depr true if it is deprecated
  2244      * @param first true if the first sentenge tags should be added
  2245      * @param htmltree the documentation tree to which the comment tags will be added
  2246      */
  2247     private void addCommentTags(Doc doc, Tag[] tags, boolean depr,
  2248             boolean first, Content htmltree) {
  2249         if(configuration.nocomment){
  2250             return;
  2252         Content div;
  2253         Content result = new RawHtml(commentTagsToString(null, doc, tags, first));
  2254         if (depr) {
  2255             Content italic = HtmlTree.I(result);
  2256             div = HtmlTree.DIV(HtmlStyle.block, italic);
  2257             htmltree.addContent(div);
  2259         else {
  2260             div = HtmlTree.DIV(HtmlStyle.block, result);
  2261             htmltree.addContent(div);
  2263         if (tags.length == 0) {
  2264             htmltree.addContent(getSpace());
  2268     /**
  2269      * Converts inline tags and text to text strings, expanding the
  2270      * inline tags along the way.  Called wherever text can contain
  2271      * an inline tag, such as in comments or in free-form text arguments
  2272      * to non-inline tags.
  2274      * @param holderTag    specific tag where comment resides
  2275      * @param doc    specific doc where comment resides
  2276      * @param tags   array of text tags and inline tags (often alternating)
  2277      *               present in the text of interest for this doc
  2278      * @param isFirstSentence  true if text is first sentence
  2279      */
  2280     public String commentTagsToString(Tag holderTag, Doc doc, Tag[] tags,
  2281             boolean isFirstSentence) {
  2282         StringBuilder result = new StringBuilder();
  2283         // Array of all possible inline tags for this javadoc run
  2284         configuration.tagletManager.checkTags(doc, tags, true);
  2285         for (int i = 0; i < tags.length; i++) {
  2286             Tag tagelem = tags[i];
  2287             String tagName = tagelem.name();
  2288             if (tagelem instanceof SeeTag) {
  2289                 result.append(seeTagToString((SeeTag)tagelem));
  2290             } else if (! tagName.equals("Text")) {
  2291                 int originalLength = result.length();
  2292                 TagletOutput output = TagletWriter.getInlineTagOuput(
  2293                     configuration.tagletManager, holderTag,
  2294                     tagelem, getTagletWriterInstance(isFirstSentence));
  2295                 result.append(output == null ? "" : output.toString());
  2296                 if (originalLength == 0 && isFirstSentence && tagelem.name().equals("@inheritDoc") && result.length() > 0) {
  2297                     break;
  2298                 } else {
  2299                         continue;
  2301             } else {
  2302                 //This is just a regular text tag.  The text may contain html links (<a>)
  2303                 //or inline tag {@docRoot}, which will be handled as special cases.
  2304                 String text = redirectRelativeLinks(tagelem.holder(), tagelem.text());
  2306                 // Replace @docRoot only if not represented by an instance of DocRootTaglet,
  2307                 // that is, only if it was not present in a source file doc comment.
  2308                 // This happens when inserted by the doclet (a few lines
  2309                 // above in this method).  [It might also happen when passed in on the command
  2310                 // line as a text argument to an option (like -header).]
  2311                 text = replaceDocRootDir(text);
  2312                 if (isFirstSentence) {
  2313                     text = removeNonInlineHtmlTags(text);
  2315                 StringTokenizer lines = new StringTokenizer(text, "\r\n", true);
  2316                 StringBuffer textBuff = new StringBuffer();
  2317                 while (lines.hasMoreTokens()) {
  2318                     StringBuilder line = new StringBuilder(lines.nextToken());
  2319                     Util.replaceTabs(configuration.sourcetab, line);
  2320                     textBuff.append(line.toString());
  2322                 result.append(textBuff);
  2325         return result.toString();
  2328     /**
  2329      * Return true if relative links should not be redirected.
  2331      * @return Return true if a relative link should not be redirected.
  2332      */
  2333     private boolean shouldNotRedirectRelativeLinks() {
  2334         return  this instanceof AnnotationTypeWriter ||
  2335                 this instanceof ClassWriter ||
  2336                 this instanceof PackageSummaryWriter;
  2339     /**
  2340      * Suppose a piece of documentation has a relative link.  When you copy
  2341      * that documetation to another place such as the index or class-use page,
  2342      * that relative link will no longer work.  We should redirect those links
  2343      * so that they will work again.
  2344      * <p>
  2345      * Here is the algorithm used to fix the link:
  2346      * <p>
  2347      * &lt;relative link&gt; => docRoot + &lt;relative path to file&gt; + &lt;relative link&gt;
  2348      * <p>
  2349      * For example, suppose com.sun.javadoc.RootDoc has this link:
  2350      * &lt;a href="package-summary.html"&gt;The package Page&lt;/a&gt;
  2351      * <p>
  2352      * If this link appeared in the index, we would redirect
  2353      * the link like this:
  2355      * &lt;a href="./com/sun/javadoc/package-summary.html"&gt;The package Page&lt;/a&gt;
  2357      * @param doc the Doc object whose documentation is being written.
  2358      * @param text the text being written.
  2360      * @return the text, with all the relative links redirected to work.
  2361      */
  2362     private String redirectRelativeLinks(Doc doc, String text) {
  2363         if (doc == null || shouldNotRedirectRelativeLinks()) {
  2364             return text;
  2367         String redirectPathFromRoot;
  2368         if (doc instanceof ClassDoc) {
  2369             redirectPathFromRoot = DirectoryManager.getDirectoryPath(((ClassDoc) doc).containingPackage());
  2370         } else if (doc instanceof MemberDoc) {
  2371             redirectPathFromRoot = DirectoryManager.getDirectoryPath(((MemberDoc) doc).containingPackage());
  2372         } else if (doc instanceof PackageDoc) {
  2373             redirectPathFromRoot = DirectoryManager.getDirectoryPath((PackageDoc) doc);
  2374         } else {
  2375             return text;
  2378         if (! redirectPathFromRoot.endsWith(DirectoryManager.URL_FILE_SEPARATOR)) {
  2379             redirectPathFromRoot += DirectoryManager.URL_FILE_SEPARATOR;
  2382         //Redirect all relative links.
  2383         int end, begin = text.toLowerCase().indexOf("<a");
  2384         if(begin >= 0){
  2385             StringBuffer textBuff = new StringBuffer(text);
  2387             while(begin >=0){
  2388                 if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
  2389                     begin = textBuff.toString().toLowerCase().indexOf("<a", begin + 1);
  2390                     continue;
  2393                 begin = textBuff.indexOf("=", begin) + 1;
  2394                 end = textBuff.indexOf(">", begin +1);
  2395                 if(begin == 0){
  2396                     //Link has no equal symbol.
  2397                     configuration.root.printWarning(
  2398                         doc.position(),
  2399                         configuration.getText("doclet.malformed_html_link_tag", text));
  2400                     break;
  2402                 if (end == -1) {
  2403                     //Break without warning.  This <a> tag is not necessarily malformed.  The text
  2404                     //might be missing '>' character because the href has an inline tag.
  2405                     break;
  2407                 if(textBuff.substring(begin, end).indexOf("\"") != -1){
  2408                     begin = textBuff.indexOf("\"", begin) + 1;
  2409                     end = textBuff.indexOf("\"", begin +1);
  2410                     if(begin == 0 || end == -1){
  2411                         //Link is missing a quote.
  2412                         break;
  2415                 String relativeLink = textBuff.substring(begin, end);
  2416                 if(!(relativeLink.toLowerCase().startsWith("mailto:") ||
  2417                      relativeLink.toLowerCase().startsWith("http:") ||
  2418                      relativeLink.toLowerCase().startsWith("https:") ||
  2419                      relativeLink.toLowerCase().startsWith("file:"))){
  2420                      relativeLink = "{@"+(new DocRootTaglet()).getName() + "}"
  2421                         + redirectPathFromRoot
  2422                         + relativeLink;
  2423                     textBuff.replace(begin, end, relativeLink);
  2425                 begin = textBuff.toString().toLowerCase().indexOf("<a", begin + 1);
  2427             return textBuff.toString();
  2429         return text;
  2432     public String removeNonInlineHtmlTags(String text) {
  2433         if (text.indexOf('<') < 0) {
  2434             return text;
  2436         String noninlinetags[] = { "<ul>", "</ul>", "<ol>", "</ol>",
  2437                 "<dl>", "</dl>", "<table>", "</table>",
  2438                 "<tr>", "</tr>", "<td>", "</td>",
  2439                 "<th>", "</th>", "<p>", "</p>",
  2440                 "<li>", "</li>", "<dd>", "</dd>",
  2441                 "<dir>", "</dir>", "<dt>", "</dt>",
  2442                 "<h1>", "</h1>", "<h2>", "</h2>",
  2443                 "<h3>", "</h3>", "<h4>", "</h4>",
  2444                 "<h5>", "</h5>", "<h6>", "</h6>",
  2445                 "<pre>", "</pre>", "<menu>", "</menu>",
  2446                 "<listing>", "</listing>", "<hr>",
  2447                 "<blockquote>", "</blockquote>",
  2448                 "<center>", "</center>",
  2449                 "<UL>", "</UL>", "<OL>", "</OL>",
  2450                 "<DL>", "</DL>", "<TABLE>", "</TABLE>",
  2451                 "<TR>", "</TR>", "<TD>", "</TD>",
  2452                 "<TH>", "</TH>", "<P>", "</P>",
  2453                 "<LI>", "</LI>", "<DD>", "</DD>",
  2454                 "<DIR>", "</DIR>", "<DT>", "</DT>",
  2455                 "<H1>", "</H1>", "<H2>", "</H2>",
  2456                 "<H3>", "</H3>", "<H4>", "</H4>",
  2457                 "<H5>", "</H5>", "<H6>", "</H6>",
  2458                 "<PRE>", "</PRE>", "<MENU>", "</MENU>",
  2459                 "<LISTING>", "</LISTING>", "<HR>",
  2460                 "<BLOCKQUOTE>", "</BLOCKQUOTE>",
  2461                 "<CENTER>", "</CENTER>"
  2462         };
  2463         for (int i = 0; i < noninlinetags.length; i++) {
  2464             text = replace(text, noninlinetags[i], "");
  2466         return text;
  2469     public String replace(String text, String tobe, String by) {
  2470         while (true) {
  2471             int startindex = text.indexOf(tobe);
  2472             if (startindex < 0) {
  2473                 return text;
  2475             int endindex = startindex + tobe.length();
  2476             StringBuilder replaced = new StringBuilder();
  2477             if (startindex > 0) {
  2478                 replaced.append(text.substring(0, startindex));
  2480             replaced.append(by);
  2481             if (text.length() > endindex) {
  2482                 replaced.append(text.substring(endindex));
  2484             text = replaced.toString();
  2488     public void printStyleSheetProperties() {
  2489         String filename = configuration.stylesheetfile;
  2490         if (filename.length() > 0) {
  2491             File stylefile = new File(filename);
  2492             String parent = stylefile.getParent();
  2493             filename = (parent == null)?
  2494                 filename:
  2495                 filename.substring(parent.length() + 1);
  2496         } else {
  2497             filename = "stylesheet.css";
  2499         filename = relativePath + filename;
  2500         link("REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"" +
  2501                  filename + "\" " + "TITLE=\"Style\"");
  2504     /**
  2505      * Returns a link to the stylesheet file.
  2507      * @return an HtmlTree for the lINK tag which provides the stylesheet location
  2508      */
  2509     public HtmlTree getStyleSheetProperties() {
  2510         String filename = configuration.stylesheetfile;
  2511         if (filename.length() > 0) {
  2512             File stylefile = new File(filename);
  2513             String parent = stylefile.getParent();
  2514             filename = (parent == null)?
  2515                 filename:
  2516                 filename.substring(parent.length() + 1);
  2517         } else {
  2518             filename = "stylesheet.css";
  2520         filename = relativePath + filename;
  2521         HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style");
  2522         return link;
  2525     /**
  2526      * According to
  2527      * <cite>The Java&trade; Language Specification</cite>,
  2528      * all the outer classes and static nested classes are core classes.
  2529      */
  2530     public boolean isCoreClass(ClassDoc cd) {
  2531         return cd.containingClass() == null || cd.isStatic();
  2534     /**
  2535      * Write the annotatation types for the given packageDoc.
  2537      * @param packageDoc the package to write annotations for.
  2538      */
  2539     public void writeAnnotationInfo(PackageDoc packageDoc) {
  2540         writeAnnotationInfo(packageDoc, packageDoc.annotations());
  2543     /**
  2544      * Adds the annotatation types for the given packageDoc.
  2546      * @param packageDoc the package to write annotations for.
  2547      * @param htmltree the documentation tree to which the annotation info will be
  2548      *        added
  2549      */
  2550     public void addAnnotationInfo(PackageDoc packageDoc, Content htmltree) {
  2551         addAnnotationInfo(packageDoc, packageDoc.annotations(), htmltree);
  2554     /**
  2555      * Write the annotatation types for the given doc.
  2557      * @param doc the doc to write annotations for.
  2558      */
  2559     public void writeAnnotationInfo(ProgramElementDoc doc) {
  2560         writeAnnotationInfo(doc, doc.annotations());
  2563     /**
  2564      * Adds the annotatation types for the given doc.
  2566      * @param packageDoc the package to write annotations for
  2567      * @param htmltree the content tree to which the annotation types will be added
  2568      */
  2569     public void addAnnotationInfo(ProgramElementDoc doc, Content htmltree) {
  2570         addAnnotationInfo(doc, doc.annotations(), htmltree);
  2573     /**
  2574      * Write the annotatation types for the given doc and parameter.
  2576      * @param indent the number of spaced to indent the parameters.
  2577      * @param doc the doc to write annotations for.
  2578      * @param param the parameter to write annotations for.
  2579      */
  2580     public boolean writeAnnotationInfo(int indent, Doc doc, Parameter param) {
  2581         return writeAnnotationInfo(indent, doc, param.annotations(), false);
  2584     /**
  2585      * Add the annotatation types for the given doc and parameter.
  2587      * @param indent the number of spaces to indent the parameters.
  2588      * @param doc the doc to write annotations for.
  2589      * @param param the parameter to write annotations for.
  2590      * @param tree the content tree to which the annotation types will be added
  2591      */
  2592     public boolean addAnnotationInfo(int indent, Doc doc, Parameter param,
  2593             Content tree) {
  2594         return addAnnotationInfo(indent, doc, param.annotations(), false, tree);
  2597     /**
  2598      * Write the annotatation types for the given doc.
  2600      * @param doc the doc to write annotations for.
  2601      * @param descList the array of {@link AnnotationDesc}.
  2602      */
  2603     private void writeAnnotationInfo(Doc doc, AnnotationDesc[] descList) {
  2604         writeAnnotationInfo(0, doc, descList, true);
  2607     /**
  2608      * Adds the annotatation types for the given doc.
  2610      * @param doc the doc to write annotations for.
  2611      * @param descList the array of {@link AnnotationDesc}.
  2612      * @param htmltree the documentation tree to which the annotation info will be
  2613      *        added
  2614      */
  2615     private void addAnnotationInfo(Doc doc, AnnotationDesc[] descList,
  2616             Content htmltree) {
  2617         addAnnotationInfo(0, doc, descList, true, htmltree);
  2620     /**
  2621      * Write the annotatation types for the given doc.
  2623      * @param indent the number of extra spaces to indent the annotations.
  2624      * @param doc the doc to write annotations for.
  2625      * @param descList the array of {@link AnnotationDesc}.
  2626      */
  2627     private boolean writeAnnotationInfo(int indent, Doc doc, AnnotationDesc[] descList, boolean lineBreak) {
  2628         List<String> annotations = getAnnotations(indent, descList, lineBreak);
  2629         if (annotations.size() == 0) {
  2630             return false;
  2632         fontNoNewLine("-1");
  2633         for (Iterator<String> iter = annotations.iterator(); iter.hasNext();) {
  2634             print(iter.next());
  2636         fontEnd();
  2637         return true;
  2640     /**
  2641      * Adds the annotatation types for the given doc.
  2643      * @param indent the number of extra spaces to indent the annotations.
  2644      * @param doc the doc to write annotations for.
  2645      * @param descList the array of {@link AnnotationDesc}.
  2646      * @param htmltree the documentation tree to which the annotation info will be
  2647      *        added
  2648      */
  2649     private boolean addAnnotationInfo(int indent, Doc doc,
  2650             AnnotationDesc[] descList, boolean lineBreak, Content htmltree) {
  2651         List<String> annotations = getAnnotations(indent, descList, lineBreak);
  2652         if (annotations.size() == 0) {
  2653             return false;
  2655         Content annotationContent;
  2656         for (Iterator<String> iter = annotations.iterator(); iter.hasNext();) {
  2657             annotationContent = new RawHtml(iter.next());
  2658             htmltree.addContent(annotationContent);
  2660         return true;
  2663    /**
  2664      * Return the string representations of the annotation types for
  2665      * the given doc.
  2667      * @param indent the number of extra spaces to indent the annotations.
  2668      * @param descList the array of {@link AnnotationDesc}.
  2669      * @param linkBreak if true, add new line between each member value.
  2670      * @return an array of strings representing the annotations being
  2671      *         documented.
  2672      */
  2673     private List<String> getAnnotations(int indent, AnnotationDesc[] descList, boolean linkBreak) {
  2674         List<String> results = new ArrayList<String>();
  2675         StringBuffer annotation;
  2676         for (int i = 0; i < descList.length; i++) {
  2677             AnnotationTypeDoc annotationDoc = descList[i].annotationType();
  2678             if (! Util.isDocumentedAnnotation(annotationDoc)){
  2679                 continue;
  2681             annotation = new StringBuffer();
  2682             LinkInfoImpl linkInfo = new LinkInfoImpl(
  2683                 LinkInfoImpl.CONTEXT_ANNOTATION, annotationDoc);
  2684             linkInfo.label = "@" + annotationDoc.name();
  2685             annotation.append(getLink(linkInfo));
  2686             AnnotationDesc.ElementValuePair[] pairs = descList[i].elementValues();
  2687             if (pairs.length > 0) {
  2688                 annotation.append('(');
  2689                 for (int j = 0; j < pairs.length; j++) {
  2690                     if (j > 0) {
  2691                         annotation.append(",");
  2692                         if (linkBreak) {
  2693                             annotation.append(DocletConstants.NL);
  2694                             int spaces = annotationDoc.name().length() + 2;
  2695                             for (int k = 0; k < (spaces + indent); k++) {
  2696                                 annotation.append(' ');
  2700                     annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
  2701                         pairs[j].element(), pairs[j].element().name(), false));
  2702                     annotation.append('=');
  2703                     AnnotationValue annotationValue = pairs[j].value();
  2704                     List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
  2705                     if (annotationValue.value() instanceof AnnotationValue[]) {
  2706                         AnnotationValue[] annotationArray =
  2707                             (AnnotationValue[]) annotationValue.value();
  2708                         for (int k = 0; k < annotationArray.length; k++) {
  2709                             annotationTypeValues.add(annotationArray[k]);
  2711                     } else {
  2712                         annotationTypeValues.add(annotationValue);
  2714                     annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
  2715                     for (Iterator<AnnotationValue> iter = annotationTypeValues.iterator(); iter.hasNext(); ) {
  2716                         annotation.append(annotationValueToString(iter.next()));
  2717                         annotation.append(iter.hasNext() ? "," : "");
  2719                     annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
  2721                 annotation.append(")");
  2723             annotation.append(linkBreak ? DocletConstants.NL : "");
  2724             results.add(annotation.toString());
  2726         return results;
  2729     private String annotationValueToString(AnnotationValue annotationValue) {
  2730         if (annotationValue.value() instanceof Type) {
  2731             Type type = (Type) annotationValue.value();
  2732             if (type.asClassDoc() != null) {
  2733                 LinkInfoImpl linkInfo = new LinkInfoImpl(
  2734                     LinkInfoImpl.CONTEXT_ANNOTATION, type);
  2735                     linkInfo.label = (type.asClassDoc().isIncluded() ?
  2736                         type.typeName() :
  2737                         type.qualifiedTypeName()) + type.dimension() + ".class";
  2738                 return getLink(linkInfo);
  2739             } else {
  2740                 return type.typeName() + type.dimension() + ".class";
  2742         } else if (annotationValue.value() instanceof AnnotationDesc) {
  2743             List<String> list = getAnnotations(0,
  2744                 new AnnotationDesc[]{(AnnotationDesc) annotationValue.value()},
  2745                     false);
  2746             StringBuffer buf = new StringBuffer();
  2747             for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
  2748                 buf.append(iter.next());
  2750             return buf.toString();
  2751         } else if (annotationValue.value() instanceof MemberDoc) {
  2752             return getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
  2753                 (MemberDoc) annotationValue.value(),
  2754                 ((MemberDoc) annotationValue.value()).name(), false);
  2755          } else {
  2756             return annotationValue.toString();
  2760     /**
  2761      * Return the configuation for this doclet.
  2763      * @return the configuration for this doclet.
  2764      */
  2765     public Configuration configuration() {
  2766         return configuration;

mercurial