Fri, 05 Oct 2012 14:16:32 -0700
7068595: html files in class-use dir do not get loaded correctly when Frames link is clicked
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1998, 2012, 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 {@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 {@docRoot}, when
139 * the HTML page for source file p/C1.java is being generated, the
140 * {@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 '&#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 if (configuration.docrootparent.length() > 0) {
163 // Search for lowercase version of {@docRoot}/..
164 index = lowerHtml.indexOf("{@docroot}/..", previndex);
165 // If next {@docRoot}/.. pattern not found, append rest of htmlstr and exit loop
166 if (index < 0) {
167 buf.append(htmlstr.substring(previndex));
168 break;
169 }
170 // If next {@docroot}/.. pattern found, append htmlstr up to start of tag
171 buf.append(htmlstr.substring(previndex, index));
172 previndex = index + 13; // length for {@docroot}/.. string
173 // Insert docrootparent absolute path where {@docRoot}/.. was located
175 buf.append(configuration.docrootparent);
176 // Append slash if next character is not a slash
177 if (previndex < htmlstr.length() && htmlstr.charAt(previndex) != '/') {
178 buf.append(DirectoryManager.URL_FILE_SEPARATOR);
179 }
180 } else {
181 // Search for lowercase version of {@docRoot}
182 index = lowerHtml.indexOf("{@docroot}", previndex);
183 // If next {@docRoot} tag not found, append rest of htmlstr and exit loop
184 if (index < 0) {
185 buf.append(htmlstr.substring(previndex));
186 break;
187 }
188 // If next {@docroot} tag found, append htmlstr up to start of tag
189 buf.append(htmlstr.substring(previndex, index));
190 previndex = index + 10; // length for {@docroot} string
191 // Insert relative path where {@docRoot} was located
192 buf.append(relativepathNoSlash);
193 // Append slash if next character is not a slash
194 if (relativepathNoSlash.length() > 0 && previndex < htmlstr.length() &&
195 htmlstr.charAt(previndex) != '/') {
196 buf.append(DirectoryManager.URL_FILE_SEPARATOR);
197 }
198 }
199 }
200 return buf.toString();
201 }
203 /**
204 * Print Html Hyper Link, with target frame. This
205 * link will only appear if page is not in a frame.
206 *
207 * @param link String name of the file.
208 * @param where Position in the file
209 * @param target Name of the target frame.
210 * @param label Tag for the link.
211 * @param strong Whether the label should be strong or not?
212 */
213 public void printNoFramesTargetHyperLink(String link, String where,
214 String target, String label,
215 boolean strong) {
216 script();
217 println(" <!--");
218 println(" if(window==top) {");
219 println(" document.writeln('"
220 + getHyperLinkString(link, where, label, strong, "", "", target) + "');");
221 println(" }");
222 println(" //-->");
223 scriptEnd();
224 noScript();
225 println(" " + getHyperLinkString(link, where, label, strong, "", "", target));
226 noScriptEnd();
227 println(DocletConstants.NL);
228 }
230 /**
231 * Get the script to show or hide the All classes link.
232 *
233 * @param id id of the element to show or hide
234 * @return a content tree for the script
235 */
236 public Content getAllClassesLinkScript(String id) {
237 HtmlTree script = new HtmlTree(HtmlTag.SCRIPT);
238 script.addAttr(HtmlAttr.TYPE, "text/javascript");
239 String scriptCode = "<!--" + DocletConstants.NL +
240 " allClassesLink = document.getElementById(\"" + id + "\");" + DocletConstants.NL +
241 " if(window==top) {" + DocletConstants.NL +
242 " allClassesLink.style.display = \"block\";" + DocletConstants.NL +
243 " }" + DocletConstants.NL +
244 " else {" + DocletConstants.NL +
245 " allClassesLink.style.display = \"none\";" + DocletConstants.NL +
246 " }" + DocletConstants.NL +
247 " //-->" + DocletConstants.NL;
248 Content scriptContent = new RawHtml(scriptCode);
249 script.addContent(scriptContent);
250 Content div = HtmlTree.DIV(script);
251 return div;
252 }
254 /**
255 * Add method information.
256 *
257 * @param method the method to be documented
258 * @param dl the content tree to which the method information will be added
259 */
260 private void addMethodInfo(MethodDoc method, Content dl) {
261 ClassDoc[] intfacs = method.containingClass().interfaces();
262 MethodDoc overriddenMethod = method.overriddenMethod();
263 // Check whether there is any implementation or overridden info to be
264 // printed. If no overridden or implementation info needs to be
265 // printed, do not print this section.
266 if ((intfacs.length > 0 &&
267 new ImplementedMethods(method, this.configuration).build().length > 0) ||
268 overriddenMethod != null) {
269 MethodWriterImpl.addImplementsInfo(this, method, dl);
270 if (overriddenMethod != null) {
271 MethodWriterImpl.addOverridden(this,
272 method.overriddenType(), overriddenMethod, dl);
273 }
274 }
275 }
277 /**
278 * Adds the tags information.
279 *
280 * @param doc the doc for which the tags will be generated
281 * @param htmltree the documentation tree to which the tags will be added
282 */
283 protected void addTagsInfo(Doc doc, Content htmltree) {
284 if (configuration.nocomment) {
285 return;
286 }
287 Content dl = new HtmlTree(HtmlTag.DL);
288 if (doc instanceof MethodDoc) {
289 addMethodInfo((MethodDoc) doc, dl);
290 }
291 TagletOutputImpl output = new TagletOutputImpl("");
292 TagletWriter.genTagOuput(configuration.tagletManager, doc,
293 configuration.tagletManager.getCustomTags(doc),
294 getTagletWriterInstance(false), output);
295 String outputString = output.toString().trim();
296 if (!outputString.isEmpty()) {
297 Content resultString = new RawHtml(outputString);
298 dl.addContent(resultString);
299 }
300 htmltree.addContent(dl);
301 }
303 /**
304 * Check whether there are any tags for Serialization Overview
305 * section to be printed.
306 *
307 * @param field the FieldDoc object to check for tags.
308 * @return true if there are tags to be printed else return false.
309 */
310 protected boolean hasSerializationOverviewTags(FieldDoc field) {
311 TagletOutputImpl output = new TagletOutputImpl("");
312 TagletWriter.genTagOuput(configuration.tagletManager, field,
313 configuration.tagletManager.getCustomTags(field),
314 getTagletWriterInstance(false), output);
315 return (!output.toString().trim().isEmpty());
316 }
318 /**
319 * Returns a TagletWriter that knows how to write HTML.
320 *
321 * @return a TagletWriter that knows how to write HTML.
322 */
323 public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
324 return new TagletWriterImpl(this, isFirstSentence);
325 }
327 protected void printTagsInfoHeader() {
328 dl();
329 }
331 protected void printTagsInfoFooter() {
332 dlEnd();
333 }
335 /**
336 * Get Package link, with target frame.
337 *
338 * @param pd The link will be to the "package-summary.html" page for this package
339 * @param target name of the target frame
340 * @param label tag for the link
341 * @return a content for the target package link
342 */
343 public Content getTargetPackageLink(PackageDoc pd, String target,
344 Content label) {
345 return getHyperLink(pathString(pd, "package-summary.html"), "", label, "", target);
346 }
348 /**
349 * Print the html file header. Also print Html page title and stylesheet
350 * default properties.
351 *
352 * @param title String window title to go in the <TITLE> tag
353 * @param metakeywords Array of String keywords for META tag. Each element
354 * of the array is assigned to a separate META tag.
355 * Pass in null for no array.
356 * @param includeScript boolean true if printing windowtitle script.
357 * False for files that appear in the left-hand frames.
358 */
359 public void printHtmlHeader(String title, String[] metakeywords,
360 boolean includeScript) {
361 println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 " +
362 "Transitional//EN\" " +
363 "\"http://www.w3.org/TR/html4/loose.dtd\">");
364 println("<!--NewPage-->");
365 html();
366 head();
367 if (! configuration.notimestamp) {
368 print("<!-- Generated by javadoc (build " + ConfigurationImpl.BUILD_DATE + ") on ");
369 print(today());
370 println(" -->");
371 }
372 if (configuration.charset.length() > 0) {
373 println("<META http-equiv=\"Content-Type\" content=\"text/html; "
374 + "charset=" + configuration.charset + "\">");
375 }
376 if ( configuration.windowtitle.length() > 0 ) {
377 title += " (" + configuration.windowtitle + ")";
378 }
379 title(title);
380 println(title);
381 titleEnd();
382 println("");
383 if (! configuration.notimestamp) {
384 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
385 println("<META NAME=\"date\" "
386 + "CONTENT=\"" + dateFormat.format(new Date()) + "\">");
387 }
388 if ( metakeywords != null ) {
389 for ( int i=0; i < metakeywords.length; i++ ) {
390 println("<META NAME=\"keywords\" "
391 + "CONTENT=\"" + metakeywords[i] + "\">");
392 }
393 }
394 println("");
395 printStyleSheetProperties();
396 println("");
397 // Don't print windowtitle script for overview-frame, allclasses-frame
398 // and package-frame
399 if (includeScript) {
400 printWinTitleScript(title);
401 }
402 println("");
403 headEnd();
404 println("");
405 body("white", includeScript);
406 }
408 /**
409 * Generates the HTML document tree and prints it out.
410 *
411 * @param metakeywords Array of String keywords for META tag. Each element
412 * of the array is assigned to a separate META tag.
413 * Pass in null for no array
414 * @param includeScript true if printing windowtitle script
415 * false for files that appear in the left-hand frames
416 * @param body the body htmltree to be included in the document
417 */
418 public void printHtmlDocument(String[] metakeywords, boolean includeScript,
419 Content body) {
420 Content htmlDocType = DocType.Transitional();
421 Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
422 Content head = new HtmlTree(HtmlTag.HEAD);
423 if (!configuration.notimestamp) {
424 Content headComment = new Comment("Generated by javadoc (version " +
425 ConfigurationImpl.BUILD_DATE + ") on " + today());
426 head.addContent(headComment);
427 }
428 if (configuration.charset.length() > 0) {
429 Content meta = HtmlTree.META("Content-Type", "text/html",
430 configuration.charset);
431 head.addContent(meta);
432 }
433 head.addContent(getTitle());
434 if (!configuration.notimestamp) {
435 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
436 Content meta = HtmlTree.META("date", dateFormat.format(new Date()));
437 head.addContent(meta);
438 }
439 if (metakeywords != null) {
440 for (int i=0; i < metakeywords.length; i++) {
441 Content meta = HtmlTree.META("keywords", metakeywords[i]);
442 head.addContent(meta);
443 }
444 }
445 head.addContent(getStyleSheetProperties());
446 Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
447 head, body);
448 Content htmlDocument = new HtmlDocument(htmlDocType,
449 htmlComment, htmlTree);
450 print(htmlDocument.toString());
451 }
453 /**
454 * Get the window title.
455 *
456 * @param title the title string to construct the complete window title
457 * @return the window title string
458 */
459 public String getWindowTitle(String title) {
460 if (configuration.windowtitle.length() > 0) {
461 title += " (" + configuration.windowtitle + ")";
462 }
463 return title;
464 }
466 /**
467 * Print 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 void printUserHeaderFooter(boolean header) {
473 em();
474 if (header) {
475 print(replaceDocRootDir(configuration.header));
476 } else {
477 if (configuration.footer.length() != 0) {
478 print(replaceDocRootDir(configuration.footer));
479 } else {
480 print(replaceDocRootDir(configuration.header));
481 }
482 }
483 emEnd();
484 }
486 /**
487 * Get user specified header and the footer.
488 *
489 * @param header if true print the user provided header else print the
490 * user provided footer.
491 */
492 public Content getUserHeaderFooter(boolean header) {
493 String content;
494 if (header) {
495 content = replaceDocRootDir(configuration.header);
496 } else {
497 if (configuration.footer.length() != 0) {
498 content = replaceDocRootDir(configuration.footer);
499 } else {
500 content = replaceDocRootDir(configuration.header);
501 }
502 }
503 Content rawContent = new RawHtml(content);
504 Content em = HtmlTree.EM(rawContent);
505 return em;
506 }
508 /**
509 * Print the user specified top.
510 */
511 public void printTop() {
512 print(replaceDocRootDir(configuration.top));
513 hr();
514 }
516 /**
517 * Adds the user specified top.
518 *
519 * @param body the content tree to which user specified top will be added
520 */
521 public void addTop(Content body) {
522 Content top = new RawHtml(replaceDocRootDir(configuration.top));
523 body.addContent(top);
524 }
526 /**
527 * Print the user specified bottom.
528 */
529 public void printBottom() {
530 hr();
531 print(replaceDocRootDir(configuration.bottom));
532 }
534 /**
535 * Adds the user specified bottom.
536 *
537 * @param body the content tree to which user specified bottom will be added
538 */
539 public void addBottom(Content body) {
540 Content bottom = new RawHtml(replaceDocRootDir(configuration.bottom));
541 Content small = HtmlTree.SMALL(bottom);
542 Content p = HtmlTree.P(HtmlStyle.legalCopy, small);
543 body.addContent(p);
544 }
546 /**
547 * Print the navigation bar for the Html page at the top and and the bottom.
548 *
549 * @param header If true print navigation bar at the top of the page else
550 * print the nevigation bar at the bottom.
551 */
552 protected void navLinks(boolean header) {
553 println("");
554 if (!configuration.nonavbar) {
555 if (header) {
556 println(DocletConstants.NL + "<!-- ========= START OF TOP NAVBAR ======= -->");
557 anchor("navbar_top");
558 println();
559 print(getHyperLinkString("", "skip-navbar_top", "", false, "",
560 configuration.getText("doclet.Skip_navigation_links"), ""));
561 } else {
562 println(DocletConstants.NL + "<!-- ======= START OF BOTTOM NAVBAR ====== -->");
563 anchor("navbar_bottom");
564 println();
565 print(getHyperLinkString("", "skip-navbar_bottom", "", false, "",
566 configuration.getText("doclet.Skip_navigation_links"), ""));
567 }
568 table(0, "100%", 1, 0);
569 tr();
570 tdColspanBgcolorStyle(2, "#EEEEFF", "NavBarCell1");
571 println("");
572 if (header) {
573 anchor("navbar_top_firstrow");
574 } else {
575 anchor("navbar_bottom_firstrow");
576 }
577 table(0, 0, 3);
578 print(" ");
579 trAlignVAlign("center", "top");
581 if (configuration.createoverview) {
582 navLinkContents();
583 }
585 if (configuration.packages.length == 1) {
586 navLinkPackage(configuration.packages[0]);
587 } else if (configuration.packages.length > 1) {
588 navLinkPackage();
589 }
591 navLinkClass();
593 if(configuration.classuse) {
594 navLinkClassUse();
595 }
596 if(configuration.createtree) {
597 navLinkTree();
598 }
599 if(!(configuration.nodeprecated ||
600 configuration.nodeprecatedlist)) {
601 navLinkDeprecated();
602 }
603 if(configuration.createindex) {
604 navLinkIndex();
605 }
606 if (!configuration.nohelp) {
607 navLinkHelp();
608 }
609 print(" ");
610 trEnd();
611 tableEnd();
612 tdEnd();
614 tdAlignVAlignRowspan("right", "top", 3);
616 printUserHeaderFooter(header);
617 tdEnd();
618 trEnd();
619 println("");
621 tr();
622 tdBgcolorStyle("white", "NavBarCell2");
623 font("-2");
624 space();
625 navLinkPrevious();
626 space();
627 println("");
628 space();
629 navLinkNext();
630 fontEnd();
631 tdEnd();
633 tdBgcolorStyle("white", "NavBarCell2");
634 font("-2");
635 print(" ");
636 navShowLists();
637 print(" ");
638 space();
639 println("");
640 space();
641 navHideLists(filename);
642 print(" ");
643 space();
644 println("");
645 space();
646 navLinkClassIndex();
647 fontEnd();
648 tdEnd();
650 trEnd();
652 printSummaryDetailLinks();
654 tableEnd();
655 if (header) {
656 aName("skip-navbar_top");
657 aEnd();
658 println(DocletConstants.NL + "<!-- ========= END OF TOP NAVBAR ========= -->");
659 } else {
660 aName("skip-navbar_bottom");
661 aEnd();
662 println(DocletConstants.NL + "<!-- ======== END OF BOTTOM NAVBAR ======= -->");
663 }
664 println("");
665 }
666 }
668 /**
669 * Adds the navigation bar for the Html page at the top and and the bottom.
670 *
671 * @param header If true print navigation bar at the top of the page else
672 * @param body the HtmlTree to which the nav links will be added
673 */
674 protected void addNavLinks(boolean header, Content body) {
675 if (!configuration.nonavbar) {
676 String allClassesId = "allclasses_";
677 HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
678 if (header) {
679 body.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
680 navDiv.addStyle(HtmlStyle.topNav);
681 allClassesId += "navbar_top";
682 Content a = getMarkerAnchor("navbar_top");
683 navDiv.addContent(a);
684 Content skipLinkContent = getHyperLink("",
685 "skip-navbar_top", HtmlTree.EMPTY, configuration.getText(
686 "doclet.Skip_navigation_links"), "");
687 navDiv.addContent(skipLinkContent);
688 } else {
689 body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
690 navDiv.addStyle(HtmlStyle.bottomNav);
691 allClassesId += "navbar_bottom";
692 Content a = getMarkerAnchor("navbar_bottom");
693 navDiv.addContent(a);
694 Content skipLinkContent = getHyperLink("",
695 "skip-navbar_bottom", HtmlTree.EMPTY, configuration.getText(
696 "doclet.Skip_navigation_links"), "");
697 navDiv.addContent(skipLinkContent);
698 }
699 if (header) {
700 navDiv.addContent(getMarkerAnchor("navbar_top_firstrow"));
701 } else {
702 navDiv.addContent(getMarkerAnchor("navbar_bottom_firstrow"));
703 }
704 HtmlTree navList = new HtmlTree(HtmlTag.UL);
705 navList.addStyle(HtmlStyle.navList);
706 navList.addAttr(HtmlAttr.TITLE, "Navigation");
707 if (configuration.createoverview) {
708 navList.addContent(getNavLinkContents());
709 }
710 if (configuration.packages.length == 1) {
711 navList.addContent(getNavLinkPackage(configuration.packages[0]));
712 } else if (configuration.packages.length > 1) {
713 navList.addContent(getNavLinkPackage());
714 }
715 navList.addContent(getNavLinkClass());
716 if(configuration.classuse) {
717 navList.addContent(getNavLinkClassUse());
718 }
719 if(configuration.createtree) {
720 navList.addContent(getNavLinkTree());
721 }
722 if(!(configuration.nodeprecated ||
723 configuration.nodeprecatedlist)) {
724 navList.addContent(getNavLinkDeprecated());
725 }
726 if(configuration.createindex) {
727 navList.addContent(getNavLinkIndex());
728 }
729 if (!configuration.nohelp) {
730 navList.addContent(getNavLinkHelp());
731 }
732 navDiv.addContent(navList);
733 Content aboutDiv = HtmlTree.DIV(HtmlStyle.aboutLanguage, getUserHeaderFooter(header));
734 navDiv.addContent(aboutDiv);
735 body.addContent(navDiv);
736 Content ulNav = HtmlTree.UL(HtmlStyle.navList, getNavLinkPrevious());
737 ulNav.addContent(getNavLinkNext());
738 Content subDiv = HtmlTree.DIV(HtmlStyle.subNav, ulNav);
739 Content ulFrames = HtmlTree.UL(HtmlStyle.navList, getNavShowLists());
740 ulFrames.addContent(getNavHideLists(filename));
741 subDiv.addContent(ulFrames);
742 HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
743 ulAllClasses.addAttr(HtmlAttr.ID, allClassesId.toString());
744 subDiv.addContent(ulAllClasses);
745 subDiv.addContent(getAllClassesLinkScript(allClassesId.toString()));
746 addSummaryDetailLinks(subDiv);
747 if (header) {
748 subDiv.addContent(getMarkerAnchor("skip-navbar_top"));
749 body.addContent(subDiv);
750 body.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
751 } else {
752 subDiv.addContent(getMarkerAnchor("skip-navbar_bottom"));
753 body.addContent(subDiv);
754 body.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
755 }
756 }
757 }
759 /**
760 * Print the word "NEXT" to indicate that no link is available. Override
761 * this method to customize next link.
762 */
763 protected void navLinkNext() {
764 navLinkNext(null);
765 }
767 /**
768 * Get the word "NEXT" to indicate that no link is available. Override
769 * this method to customize next link.
770 *
771 * @return a content tree for the link
772 */
773 protected Content getNavLinkNext() {
774 return getNavLinkNext(null);
775 }
777 /**
778 * Print the word "PREV" to indicate that no link is available. Override
779 * this method to customize prev link.
780 */
781 protected void navLinkPrevious() {
782 navLinkPrevious(null);
783 }
785 /**
786 * Get the word "PREV" to indicate that no link is available. Override
787 * this method to customize prev link.
788 *
789 * @return a content tree for the link
790 */
791 protected Content getNavLinkPrevious() {
792 return getNavLinkPrevious(null);
793 }
795 /**
796 * Do nothing. This is the default method.
797 */
798 protected void printSummaryDetailLinks() {
799 }
801 /**
802 * Do nothing. This is the default method.
803 */
804 protected void addSummaryDetailLinks(Content navDiv) {
805 }
807 /**
808 * Print link to the "overview-summary.html" page.
809 */
810 protected void navLinkContents() {
811 navCellStart();
812 printHyperLink(relativePath + "overview-summary.html", "",
813 configuration.getText("doclet.Overview"), true, "NavBarFont1");
814 navCellEnd();
815 }
817 /**
818 * Get link to the "overview-summary.html" page.
819 *
820 * @return a content tree for the link
821 */
822 protected Content getNavLinkContents() {
823 Content linkContent = getHyperLink(relativePath +
824 "overview-summary.html", "", overviewLabel, "", "");
825 Content li = HtmlTree.LI(linkContent);
826 return li;
827 }
829 /**
830 * Description for a cell in the navigation bar.
831 */
832 protected void navCellStart() {
833 print(" ");
834 tdBgcolorStyle("#EEEEFF", "NavBarCell1");
835 print(" ");
836 }
838 /**
839 * Description for a cell in the navigation bar, but with reverse
840 * high-light effect.
841 */
842 protected void navCellRevStart() {
843 print(" ");
844 tdBgcolorStyle("#FFFFFF", "NavBarCell1Rev");
845 print(" ");
846 space();
847 }
849 /**
850 * Closing tag for navigation bar cell.
851 */
852 protected void navCellEnd() {
853 space();
854 tdEnd();
855 }
857 /**
858 * Print link to the "package-summary.html" page for the package passed.
859 *
860 * @param pkg Package to which link will be generated.
861 */
862 protected void navLinkPackage(PackageDoc pkg) {
863 navCellStart();
864 printPackageLink(pkg, configuration.getText("doclet.Package"), true,
865 "NavBarFont1");
866 navCellEnd();
867 }
869 /**
870 * Get link to the "package-summary.html" page for the package passed.
871 *
872 * @param pkg Package to which link will be generated
873 * @return a content tree for the link
874 */
875 protected Content getNavLinkPackage(PackageDoc pkg) {
876 Content linkContent = getPackageLink(pkg,
877 packageLabel);
878 Content li = HtmlTree.LI(linkContent);
879 return li;
880 }
882 /**
883 * Print the word "Package" in the navigation bar cell, to indicate that
884 * link is not available here.
885 */
886 protected void navLinkPackage() {
887 navCellStart();
888 fontStyle("NavBarFont1");
889 printText("doclet.Package");
890 fontEnd();
891 navCellEnd();
892 }
894 /**
895 * Get the word "Package" , to indicate that link is not available here.
896 *
897 * @return a content tree for the link
898 */
899 protected Content getNavLinkPackage() {
900 Content li = HtmlTree.LI(packageLabel);
901 return li;
902 }
904 /**
905 * Print the word "Use" in the navigation bar cell, to indicate that link
906 * is not available.
907 */
908 protected void navLinkClassUse() {
909 navCellStart();
910 fontStyle("NavBarFont1");
911 printText("doclet.navClassUse");
912 fontEnd();
913 navCellEnd();
914 }
916 /**
917 * Get the word "Use", to indicate that link is not available.
918 *
919 * @return a content tree for the link
920 */
921 protected Content getNavLinkClassUse() {
922 Content li = HtmlTree.LI(useLabel);
923 return li;
924 }
926 /**
927 * Print link for previous file.
928 *
929 * @param prev File name for the prev link.
930 */
931 public void navLinkPrevious(String prev) {
932 String tag = configuration.getText("doclet.Prev");
933 if (prev != null) {
934 printHyperLink(prev, "", tag, true) ;
935 } else {
936 print(tag);
937 }
938 }
940 /**
941 * Get link for previous file.
942 *
943 * @param prev File name for the prev link
944 * @return a content tree for the link
945 */
946 public Content getNavLinkPrevious(String prev) {
947 Content li;
948 if (prev != null) {
949 li = HtmlTree.LI(getHyperLink(prev, "", prevLabel, "", ""));
950 }
951 else
952 li = HtmlTree.LI(prevLabel);
953 return li;
954 }
956 /**
957 * Print link for next file. If next is null, just print the label
958 * without linking it anywhere.
959 *
960 * @param next File name for the next link.
961 */
962 public void navLinkNext(String next) {
963 String tag = configuration.getText("doclet.Next");
964 if (next != null) {
965 printHyperLink(next, "", tag, true);
966 } else {
967 print(tag);
968 }
969 }
971 /**
972 * Get link for next file. If next is null, just print the label
973 * without linking it anywhere.
974 *
975 * @param next File name for the next link
976 * @return a content tree for the link
977 */
978 public Content getNavLinkNext(String next) {
979 Content li;
980 if (next != null) {
981 li = HtmlTree.LI(getHyperLink(next, "", nextLabel, "", ""));
982 }
983 else
984 li = HtmlTree.LI(nextLabel);
985 return li;
986 }
988 /**
989 * Print "FRAMES" link, to switch to the frame version of the output.
990 *
991 * @param link File to be linked, "index.html".
992 */
993 protected void navShowLists(String link) {
994 print(getHyperLinkString(link + "?" + path + filename, "",
995 configuration.getText("doclet.FRAMES"), true, "", "", "_top"));
996 }
998 /**
999 * Get "FRAMES" link, to switch to the frame version of the output.
1000 *
1001 * @param link File to be linked, "index.html"
1002 * @return a content tree for the link
1003 */
1004 protected Content getNavShowLists(String link) {
1005 Content framesContent = getHyperLink(link + "?" + path +
1006 filename, "", framesLabel, "", "_top");
1007 Content li = HtmlTree.LI(framesContent);
1008 return li;
1009 }
1011 /**
1012 * Print "FRAMES" link, to switch to the frame version of the output.
1013 */
1014 protected void navShowLists() {
1015 navShowLists(relativePath + "index.html");
1016 }
1018 /**
1019 * Get "FRAMES" link, to switch to the frame version of the output.
1020 *
1021 * @return a content tree for the link
1022 */
1023 protected Content getNavShowLists() {
1024 return getNavShowLists(relativePath + "index.html");
1025 }
1027 /**
1028 * Print "NO FRAMES" link, to switch to the non-frame version of the output.
1029 *
1030 * @param link File to be linked.
1031 */
1032 protected void navHideLists(String link) {
1033 print(getHyperLinkString(link, "", configuration.getText("doclet.NO_FRAMES"),
1034 true, "", "", "_top"));
1035 }
1037 /**
1038 * Get "NO FRAMES" link, to switch to the non-frame version of the output.
1039 *
1040 * @param link File to be linked
1041 * @return a content tree for the link
1042 */
1043 protected Content getNavHideLists(String link) {
1044 Content noFramesContent = getHyperLink(link, "", noframesLabel, "", "_top");
1045 Content li = HtmlTree.LI(noFramesContent);
1046 return li;
1047 }
1049 /**
1050 * Print "Tree" link in the navigation bar. If there is only one package
1051 * specified on the command line, then the "Tree" link will be to the
1052 * only "package-tree.html" file otherwise it will be to the
1053 * "overview-tree.html" file.
1054 */
1055 protected void navLinkTree() {
1056 navCellStart();
1057 PackageDoc[] packages = configuration.root.specifiedPackages();
1058 if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) {
1059 printHyperLink(pathString(packages[0], "package-tree.html"), "",
1060 configuration.getText("doclet.Tree"), true, "NavBarFont1");
1061 } else {
1062 printHyperLink(relativePath + "overview-tree.html", "",
1063 configuration.getText("doclet.Tree"), true, "NavBarFont1");
1064 }
1065 navCellEnd();
1066 }
1068 /**
1069 * Get "Tree" link in the navigation bar. If there is only one package
1070 * specified on the command line, then the "Tree" link will be to the
1071 * only "package-tree.html" file otherwise it will be to the
1072 * "overview-tree.html" file.
1073 *
1074 * @return a content tree for the link
1075 */
1076 protected Content getNavLinkTree() {
1077 Content treeLinkContent;
1078 PackageDoc[] packages = configuration.root.specifiedPackages();
1079 if (packages.length == 1 && configuration.root.specifiedClasses().length == 0) {
1080 treeLinkContent = getHyperLink(pathString(packages[0],
1081 "package-tree.html"), "", treeLabel,
1082 "", "");
1083 } else {
1084 treeLinkContent = getHyperLink(relativePath + "overview-tree.html",
1085 "", treeLabel, "", "");
1086 }
1087 Content li = HtmlTree.LI(treeLinkContent);
1088 return li;
1089 }
1091 /**
1092 * Get the overview tree link for the main tree.
1093 *
1094 * @param label the label for the link
1095 * @return a content tree for the link
1096 */
1097 protected Content getNavLinkMainTree(String label) {
1098 Content mainTreeContent = getHyperLink(relativePath + "overview-tree.html",
1099 new StringContent(label));
1100 Content li = HtmlTree.LI(mainTreeContent);
1101 return li;
1102 }
1104 /**
1105 * Print the word "Class" in the navigation bar cell, to indicate that
1106 * class link is not available.
1107 */
1108 protected void navLinkClass() {
1109 navCellStart();
1110 fontStyle("NavBarFont1");
1111 printText("doclet.Class");
1112 fontEnd();
1113 navCellEnd();
1114 }
1116 /**
1117 * Get the word "Class", to indicate that class link is not available.
1118 *
1119 * @return a content tree for the link
1120 */
1121 protected Content getNavLinkClass() {
1122 Content li = HtmlTree.LI(classLabel);
1123 return li;
1124 }
1126 /**
1127 * Print "Deprecated" API link in the navigation bar.
1128 */
1129 protected void navLinkDeprecated() {
1130 navCellStart();
1131 printHyperLink(relativePath + "deprecated-list.html", "",
1132 configuration.getText("doclet.navDeprecated"), true, "NavBarFont1");
1133 navCellEnd();
1134 }
1136 /**
1137 * Get "Deprecated" API link in the navigation bar.
1138 *
1139 * @return a content tree for the link
1140 */
1141 protected Content getNavLinkDeprecated() {
1142 Content linkContent = getHyperLink(relativePath +
1143 "deprecated-list.html", "", deprecatedLabel, "", "");
1144 Content li = HtmlTree.LI(linkContent);
1145 return li;
1146 }
1148 /**
1149 * Print link for generated index. If the user has used "-splitindex"
1150 * command line option, then link to file "index-files/index-1.html" is
1151 * generated otherwise link to file "index-all.html" is generated.
1152 */
1153 protected void navLinkClassIndex() {
1154 printNoFramesTargetHyperLink(relativePath +
1155 AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES,
1156 "", "", configuration.getText("doclet.All_Classes"), true);
1157 }
1159 /**
1160 * Get link for generated index. If the user has used "-splitindex"
1161 * command line option, then link to file "index-files/index-1.html" is
1162 * generated otherwise link to file "index-all.html" is generated.
1163 *
1164 * @return a content tree for the link
1165 */
1166 protected Content getNavLinkClassIndex() {
1167 Content allClassesContent = getHyperLink(relativePath +
1168 AllClassesFrameWriter.OUTPUT_FILE_NAME_NOFRAMES, "",
1169 allclassesLabel, "", "");
1170 Content li = HtmlTree.LI(allClassesContent);
1171 return li;
1172 }
1173 /**
1174 * Print link for generated class index.
1175 */
1176 protected void navLinkIndex() {
1177 navCellStart();
1178 printHyperLink(relativePath +
1179 (configuration.splitindex?
1180 DirectoryManager.getPath("index-files") +
1181 fileseparator: "") +
1182 (configuration.splitindex?
1183 "index-1.html" : "index-all.html"), "",
1184 configuration.getText("doclet.Index"), true, "NavBarFont1");
1185 navCellEnd();
1186 }
1188 /**
1189 * Get link for generated class index.
1190 *
1191 * @return a content tree for the link
1192 */
1193 protected Content getNavLinkIndex() {
1194 Content linkContent = getHyperLink(relativePath +(configuration.splitindex?
1195 DirectoryManager.getPath("index-files") + fileseparator: "") +
1196 (configuration.splitindex?"index-1.html" : "index-all.html"), "",
1197 indexLabel, "", "");
1198 Content li = HtmlTree.LI(linkContent);
1199 return li;
1200 }
1202 /**
1203 * Print help file link. If user has provided a help file, then generate a
1204 * link to the user given file, which is already copied to current or
1205 * destination directory.
1206 */
1207 protected void navLinkHelp() {
1208 String helpfilenm = configuration.helpfile;
1209 if (helpfilenm.equals("")) {
1210 helpfilenm = "help-doc.html";
1211 } else {
1212 int lastsep;
1213 if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) {
1214 helpfilenm = helpfilenm.substring(lastsep + 1);
1215 }
1216 }
1217 navCellStart();
1218 printHyperLink(relativePath + helpfilenm, "",
1219 configuration.getText("doclet.Help"), true, "NavBarFont1");
1220 navCellEnd();
1221 }
1223 /**
1224 * Get help file link. If user has provided a help file, then generate a
1225 * link to the user given file, which is already copied to current or
1226 * destination directory.
1227 *
1228 * @return a content tree for the link
1229 */
1230 protected Content getNavLinkHelp() {
1231 String helpfilenm = configuration.helpfile;
1232 if (helpfilenm.equals("")) {
1233 helpfilenm = "help-doc.html";
1234 } else {
1235 int lastsep;
1236 if ((lastsep = helpfilenm.lastIndexOf(File.separatorChar)) != -1) {
1237 helpfilenm = helpfilenm.substring(lastsep + 1);
1238 }
1239 }
1240 Content linkContent = getHyperLink(relativePath + helpfilenm, "",
1241 helpLabel, "", "");
1242 Content li = HtmlTree.LI(linkContent);
1243 return li;
1244 }
1246 /**
1247 * Print the word "Detail" in the navigation bar. No link is available.
1248 */
1249 protected void navDetail() {
1250 printText("doclet.Detail");
1251 }
1253 /**
1254 * Print the word "Summary" in the navigation bar. No link is available.
1255 */
1256 protected void navSummary() {
1257 printText("doclet.Summary");
1258 }
1260 /**
1261 * Print the Html table tag for the index summary tables. The table tag
1262 * printed is
1263 * {@code <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%"> }
1264 */
1265 public void tableIndexSummary() {
1266 table(1, "100%", 3, 0);
1267 }
1269 /**
1270 * Print the Html table tag for the index summary tables.
1271 *
1272 * @param summary the summary for the table tag summary attribute.
1273 */
1274 public void tableIndexSummary(String summary) {
1275 table(1, "100%", 3, 0, summary);
1276 }
1278 /**
1279 * Same as {@link #tableIndexSummary()}.
1280 */
1281 public void tableIndexDetail() {
1282 table(1, "100%", 3, 0);
1283 }
1285 /**
1286 * Print Html tag for table elements. The tag printed is
1287 * <TD ALIGN="right" VALIGN="top" WIDTH="1%">.
1288 */
1289 public void tdIndex() {
1290 print("<TD ALIGN=\"right\" VALIGN=\"top\" WIDTH=\"1%\">");
1291 }
1293 /**
1294 * Print table caption.
1295 */
1296 public void tableCaptionStart() {
1297 captionStyle("TableCaption");
1298 }
1300 /**
1301 * Print table sub-caption.
1302 */
1303 public void tableSubCaptionStart() {
1304 captionStyle("TableSubCaption");
1305 }
1307 /**
1308 * Print table caption end tags.
1309 */
1310 public void tableCaptionEnd() {
1311 captionEnd();
1312 }
1314 /**
1315 * Print summary table header.
1316 */
1317 public void summaryTableHeader(String[] header, String scope) {
1318 tr();
1319 for ( int i=0; i < header.length; i++ ) {
1320 thScopeNoWrap("TableHeader", scope);
1321 print(header[i]);
1322 thEnd();
1323 }
1324 trEnd();
1325 }
1327 /**
1328 * Get summary table header.
1329 *
1330 * @param header the header for the table
1331 * @param scope the scope of the headers
1332 * @return a content tree for the header
1333 */
1334 public Content getSummaryTableHeader(String[] header, String scope) {
1335 Content tr = new HtmlTree(HtmlTag.TR);
1336 int size = header.length;
1337 Content tableHeader;
1338 if (size == 1) {
1339 tableHeader = new StringContent(header[0]);
1340 tr.addContent(HtmlTree.TH(HtmlStyle.colOne, scope, tableHeader));
1341 return tr;
1342 }
1343 for (int i = 0; i < size; i++) {
1344 tableHeader = new StringContent(header[i]);
1345 if(i == 0)
1346 tr.addContent(HtmlTree.TH(HtmlStyle.colFirst, scope, tableHeader));
1347 else if(i == (size - 1))
1348 tr.addContent(HtmlTree.TH(HtmlStyle.colLast, scope, tableHeader));
1349 else
1350 tr.addContent(HtmlTree.TH(scope, tableHeader));
1351 }
1352 return tr;
1353 }
1355 /**
1356 * Get table caption.
1357 *
1358 * @param rawText the caption for the table which could be raw Html
1359 * @return a content tree for the caption
1360 */
1361 public Content getTableCaption(String rawText) {
1362 Content title = new RawHtml(rawText);
1363 Content captionSpan = HtmlTree.SPAN(title);
1364 Content space = getSpace();
1365 Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
1366 Content caption = HtmlTree.CAPTION(captionSpan);
1367 caption.addContent(tabSpan);
1368 return caption;
1369 }
1371 /**
1372 * Get the marker anchor which will be added to the documentation tree.
1373 *
1374 * @param anchorName the anchor name attribute
1375 * @return a content tree for the marker anchor
1376 */
1377 public Content getMarkerAnchor(String anchorName) {
1378 return getMarkerAnchor(anchorName, null);
1379 }
1381 /**
1382 * Get the marker anchor which will be added to the documentation tree.
1383 *
1384 * @param anchorName the anchor name attribute
1385 * @param anchorContent the content that should be added to the anchor
1386 * @return a content tree for the marker anchor
1387 */
1388 public Content getMarkerAnchor(String anchorName, Content anchorContent) {
1389 if (anchorContent == null)
1390 anchorContent = new Comment(" ");
1391 Content markerAnchor = HtmlTree.A_NAME(anchorName, anchorContent);
1392 return markerAnchor;
1393 }
1395 /**
1396 * Returns a packagename content.
1397 *
1398 * @param packageDoc the package to check
1399 * @return package name content
1400 */
1401 public Content getPackageName(PackageDoc packageDoc) {
1402 return packageDoc == null || packageDoc.name().length() == 0 ?
1403 defaultPackageLabel :
1404 getPackageLabel(packageDoc.name());
1405 }
1407 /**
1408 * Returns a package name label.
1409 *
1410 * @param parsedName the package name
1411 * @return the package name content
1412 */
1413 public Content getPackageLabel(String packageName) {
1414 return new StringContent(packageName);
1415 }
1417 /**
1418 * Add package deprecation information to the documentation tree
1419 *
1420 * @param deprPkgs list of deprecated packages
1421 * @param headingKey the caption for the deprecated package table
1422 * @param tableSummary the summary for the deprecated package table
1423 * @param tableHeader table headers for the deprecated package table
1424 * @param contentTree the content tree to which the deprecated package table will be added
1425 */
1426 protected void addPackageDeprecatedAPI(List<Doc> deprPkgs, String headingKey,
1427 String tableSummary, String[] tableHeader, Content contentTree) {
1428 if (deprPkgs.size() > 0) {
1429 Content table = HtmlTree.TABLE(0, 3, 0, tableSummary,
1430 getTableCaption(configuration().getText(headingKey)));
1431 table.addContent(getSummaryTableHeader(tableHeader, "col"));
1432 Content tbody = new HtmlTree(HtmlTag.TBODY);
1433 for (int i = 0; i < deprPkgs.size(); i++) {
1434 PackageDoc pkg = (PackageDoc) deprPkgs.get(i);
1435 HtmlTree td = HtmlTree.TD(HtmlStyle.colOne,
1436 getPackageLink(pkg, getPackageName(pkg)));
1437 if (pkg.tags("deprecated").length > 0) {
1438 addInlineDeprecatedComment(pkg, pkg.tags("deprecated")[0], td);
1439 }
1440 HtmlTree tr = HtmlTree.TR(td);
1441 if (i % 2 == 0) {
1442 tr.addStyle(HtmlStyle.altColor);
1443 } else {
1444 tr.addStyle(HtmlStyle.rowColor);
1445 }
1446 tbody.addContent(tr);
1447 }
1448 table.addContent(tbody);
1449 Content li = HtmlTree.LI(HtmlStyle.blockList, table);
1450 Content ul = HtmlTree.UL(HtmlStyle.blockList, li);
1451 contentTree.addContent(ul);
1452 }
1453 }
1455 /**
1456 * Prine table header information about color, column span and the font.
1457 *
1458 * @param color Background color.
1459 * @param span Column span.
1460 */
1461 public void tableHeaderStart(String color, int span) {
1462 trBgcolorStyle(color, "TableHeadingColor");
1463 thAlignColspan("left", span);
1464 font("+2");
1465 }
1467 /**
1468 * Print table header for the inherited members summary tables. Print the
1469 * background color information.
1470 *
1471 * @param color Background color.
1472 */
1473 public void tableInheritedHeaderStart(String color) {
1474 trBgcolorStyle(color, "TableSubHeadingColor");
1475 thAlign("left");
1476 }
1478 /**
1479 * Print "Use" table header. Print the background color and the column span.
1480 *
1481 * @param color Background color.
1482 */
1483 public void tableUseInfoHeaderStart(String color) {
1484 trBgcolorStyle(color, "TableSubHeadingColor");
1485 thAlignColspan("left", 2);
1486 }
1488 /**
1489 * Print table header with the background color with default column span 2.
1490 *
1491 * @param color Background color.
1492 */
1493 public void tableHeaderStart(String color) {
1494 tableHeaderStart(color, 2);
1495 }
1497 /**
1498 * Print table header with the column span, with the default color #CCCCFF.
1499 *
1500 * @param span Column span.
1501 */
1502 public void tableHeaderStart(int span) {
1503 tableHeaderStart("#CCCCFF", span);
1504 }
1506 /**
1507 * Print table header with default column span 2 and default color #CCCCFF.
1508 */
1509 public void tableHeaderStart() {
1510 tableHeaderStart(2);
1511 }
1513 /**
1514 * Print table header end tags for font, column and row.
1515 */
1516 public void tableHeaderEnd() {
1517 fontEnd();
1518 thEnd();
1519 trEnd();
1520 }
1522 /**
1523 * Print table header end tags in inherited tables for column and row.
1524 */
1525 public void tableInheritedHeaderEnd() {
1526 thEnd();
1527 trEnd();
1528 }
1530 /**
1531 * Print the summary table row cell attribute width.
1532 *
1533 * @param width Width of the table cell.
1534 */
1535 public void summaryRow(int width) {
1536 if (width != 0) {
1537 tdWidth(width + "%");
1538 } else {
1539 td();
1540 }
1541 }
1543 /**
1544 * Print the summary table row cell end tag.
1545 */
1546 public void summaryRowEnd() {
1547 tdEnd();
1548 }
1550 /**
1551 * Print the heading in Html {@literal <H2>} format.
1552 *
1553 * @param str The Header string.
1554 */
1555 public void printIndexHeading(String str) {
1556 h2();
1557 print(str);
1558 h2End();
1559 }
1561 /**
1562 * Print Html tag <FRAMESET=arg>.
1563 *
1564 * @param arg Argument for the tag.
1565 */
1566 public void frameSet(String arg) {
1567 println("<FRAMESET " + arg + ">");
1568 }
1570 /**
1571 * Print Html closing tag </FRAMESET>.
1572 */
1573 public void frameSetEnd() {
1574 println("</FRAMESET>");
1575 }
1577 /**
1578 * Print Html tag <FRAME=arg>.
1579 *
1580 * @param arg Argument for the tag.
1581 */
1582 public void frame(String arg) {
1583 println("<FRAME " + arg + ">");
1584 }
1586 /**
1587 * Print Html closing tag </FRAME>.
1588 */
1589 public void frameEnd() {
1590 println("</FRAME>");
1591 }
1593 /**
1594 * Return path to the class page for a classdoc. For example, the class
1595 * name is "java.lang.Object" and if the current file getting generated is
1596 * "java/io/File.html", then the path string to the class, returned is
1597 * "../../java/lang.Object.html".
1598 *
1599 * @param cd Class to which the path is requested.
1600 */
1601 protected String pathToClass(ClassDoc cd) {
1602 return pathString(cd.containingPackage(), cd.name() + ".html");
1603 }
1605 /**
1606 * Return the path to the class page for a classdoc. Works same as
1607 * {@link #pathToClass(ClassDoc)}.
1608 *
1609 * @param cd Class to which the path is requested.
1610 * @param name Name of the file(doesn't include path).
1611 */
1612 protected String pathString(ClassDoc cd, String name) {
1613 return pathString(cd.containingPackage(), name);
1614 }
1616 /**
1617 * Return path to the given file name in the given package. So if the name
1618 * passed is "Object.html" and the name of the package is "java.lang", and
1619 * if the relative path is "../.." then returned string will be
1620 * "../../java/lang/Object.html"
1621 *
1622 * @param pd Package in which the file name is assumed to be.
1623 * @param name File name, to which path string is.
1624 */
1625 protected String pathString(PackageDoc pd, String name) {
1626 StringBuffer buf = new StringBuffer(relativePath);
1627 buf.append(DirectoryManager.getPathToPackage(pd, name));
1628 return buf.toString();
1629 }
1631 /**
1632 * Print the link to the given package.
1633 *
1634 * @param pkg the package to link to.
1635 * @param label the label for the link.
1636 * @param isStrong true if the label should be strong.
1637 */
1638 public void printPackageLink(PackageDoc pkg, String label, boolean isStrong) {
1639 print(getPackageLinkString(pkg, label, isStrong));
1640 }
1642 /**
1643 * Print the link to the given package.
1644 *
1645 * @param pkg the package to link to.
1646 * @param label the label for the link.
1647 * @param isStrong true if the label should be strong.
1648 * @param style the font of the package link label.
1649 */
1650 public void printPackageLink(PackageDoc pkg, String label, boolean isStrong,
1651 String style) {
1652 print(getPackageLinkString(pkg, label, isStrong, style));
1653 }
1655 /**
1656 * Return the link to the given package.
1657 *
1658 * @param pkg the package to link to.
1659 * @param label the label for the link.
1660 * @param isStrong true if the label should be strong.
1661 * @return the link to the given package.
1662 */
1663 public String getPackageLinkString(PackageDoc pkg, String label,
1664 boolean isStrong) {
1665 return getPackageLinkString(pkg, label, isStrong, "");
1666 }
1668 /**
1669 * Return the link to the given package.
1670 *
1671 * @param pkg the package to link to.
1672 * @param label the label for the link.
1673 * @param isStrong true if the label should be strong.
1674 * @param style the font of the package link label.
1675 * @return the link to the given package.
1676 */
1677 public String getPackageLinkString(PackageDoc pkg, String label, boolean isStrong,
1678 String style) {
1679 boolean included = pkg != null && pkg.isIncluded();
1680 if (! included) {
1681 PackageDoc[] packages = configuration.packages;
1682 for (int i = 0; i < packages.length; i++) {
1683 if (packages[i].equals(pkg)) {
1684 included = true;
1685 break;
1686 }
1687 }
1688 }
1689 if (included || pkg == null) {
1690 return getHyperLinkString(pathString(pkg, "package-summary.html"),
1691 "", label, isStrong, style);
1692 } else {
1693 String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
1694 if (crossPkgLink != null) {
1695 return getHyperLinkString(crossPkgLink, "", label, isStrong, style);
1696 } else {
1697 return label;
1698 }
1699 }
1700 }
1702 /**
1703 * Return the link to the given package.
1704 *
1705 * @param pkg the package to link to.
1706 * @param label the label for the link.
1707 * @return a content tree for the package link.
1708 */
1709 public Content getPackageLink(PackageDoc pkg, Content label) {
1710 boolean included = pkg != null && pkg.isIncluded();
1711 if (! included) {
1712 PackageDoc[] packages = configuration.packages;
1713 for (int i = 0; i < packages.length; i++) {
1714 if (packages[i].equals(pkg)) {
1715 included = true;
1716 break;
1717 }
1718 }
1719 }
1720 if (included || pkg == null) {
1721 return getHyperLink(pathString(pkg, "package-summary.html"),
1722 "", label);
1723 } else {
1724 String crossPkgLink = getCrossPackageLink(Util.getPackageName(pkg));
1725 if (crossPkgLink != null) {
1726 return getHyperLink(crossPkgLink, "", label);
1727 } else {
1728 return label;
1729 }
1730 }
1731 }
1733 public String italicsClassName(ClassDoc cd, boolean qual) {
1734 String name = (qual)? cd.qualifiedName(): cd.name();
1735 return (cd.isInterface())? italicsText(name): name;
1736 }
1738 public void printSrcLink(ProgramElementDoc d, String label) {
1739 if (d == null) {
1740 return;
1741 }
1742 ClassDoc cd = d.containingClass();
1743 if (cd == null) {
1744 //d must be a class doc since in has no containing class.
1745 cd = (ClassDoc) d;
1746 }
1747 String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
1748 + DirectoryManager.getDirectoryPath(cd.containingPackage())
1749 + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(d);
1750 printHyperLink(href, "", label, true);
1751 }
1753 /**
1754 * Add the link to the content tree.
1755 *
1756 * @param doc program element doc for which the link will be added
1757 * @param label label for the link
1758 * @param htmltree the content tree to which the link will be added
1759 */
1760 public void addSrcLink(ProgramElementDoc doc, Content label, Content htmltree) {
1761 if (doc == null) {
1762 return;
1763 }
1764 ClassDoc cd = doc.containingClass();
1765 if (cd == null) {
1766 //d must be a class doc since in has no containing class.
1767 cd = (ClassDoc) doc;
1768 }
1769 String href = relativePath + DocletConstants.SOURCE_OUTPUT_DIR_NAME
1770 + DirectoryManager.getDirectoryPath(cd.containingPackage())
1771 + cd.name() + ".html#" + SourceToHTMLConverter.getAnchorName(doc);
1772 Content linkContent = getHyperLink(href, "", label, "", "");
1773 htmltree.addContent(linkContent);
1774 }
1776 /**
1777 * Return the link to the given class.
1778 *
1779 * @param linkInfo the information about the link.
1780 *
1781 * @return the link for the given class.
1782 */
1783 public String getLink(LinkInfoImpl linkInfo) {
1784 LinkFactoryImpl factory = new LinkFactoryImpl(this);
1785 String link = ((LinkOutputImpl) factory.getLinkOutput(linkInfo)).toString();
1786 displayLength += linkInfo.displayLength;
1787 return link;
1788 }
1790 /**
1791 * Return the type parameters for the given class.
1792 *
1793 * @param linkInfo the information about the link.
1794 * @return the type for the given class.
1795 */
1796 public String getTypeParameterLinks(LinkInfoImpl linkInfo) {
1797 LinkFactoryImpl factory = new LinkFactoryImpl(this);
1798 return ((LinkOutputImpl)
1799 factory.getTypeParameterLinks(linkInfo, false)).toString();
1800 }
1802 /**
1803 * Print the link to the given class.
1804 */
1805 public void printLink(LinkInfoImpl linkInfo) {
1806 print(getLink(linkInfo));
1807 }
1809 /*************************************************************
1810 * Return a class cross link to external class documentation.
1811 * The name must be fully qualified to determine which package
1812 * the class is in. The -link option does not allow users to
1813 * link to external classes in the "default" package.
1814 *
1815 * @param qualifiedClassName the qualified name of the external class.
1816 * @param refMemName the name of the member being referenced. This should
1817 * be null or empty string if no member is being referenced.
1818 * @param label the label for the external link.
1819 * @param strong true if the link should be strong.
1820 * @param style the style of the link.
1821 * @param code true if the label should be code font.
1822 */
1823 public String getCrossClassLink(String qualifiedClassName, String refMemName,
1824 String label, boolean strong, String style,
1825 boolean code) {
1826 String className = "",
1827 packageName = qualifiedClassName == null ? "" : qualifiedClassName;
1828 int periodIndex;
1829 while((periodIndex = packageName.lastIndexOf('.')) != -1) {
1830 className = packageName.substring(periodIndex + 1, packageName.length()) +
1831 (className.length() > 0 ? "." + className : "");
1832 String defaultLabel = code ? getCode() + className + getCodeEnd() : className;
1833 packageName = packageName.substring(0, periodIndex);
1834 if (getCrossPackageLink(packageName) != null) {
1835 //The package exists in external documentation, so link to the external
1836 //class (assuming that it exists). This is definitely a limitation of
1837 //the -link option. There are ways to determine if an external package
1838 //exists, but no way to determine if the external class exists. We just
1839 //have to assume that it does.
1840 return getHyperLinkString(
1841 configuration.extern.getExternalLink(packageName, relativePath,
1842 className + ".html?is-external=true"),
1843 refMemName == null ? "" : refMemName,
1844 label == null || label.length() == 0 ? defaultLabel : label,
1845 strong, style,
1846 configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
1847 "");
1848 }
1849 }
1850 return null;
1851 }
1853 public boolean isClassLinkable(ClassDoc cd) {
1854 if (cd.isIncluded()) {
1855 return configuration.isGeneratedDoc(cd);
1856 }
1857 return configuration.extern.isExternal(cd);
1858 }
1860 public String getCrossPackageLink(String pkgName) {
1861 return configuration.extern.getExternalLink(pkgName, relativePath,
1862 "package-summary.html?is-external=true");
1863 }
1865 /**
1866 * Get the class link.
1867 *
1868 * @param context the id of the context where the link will be added
1869 * @param cd the class doc to link to
1870 * @return a content tree for the link
1871 */
1872 public Content getQualifiedClassLink(int context, ClassDoc cd) {
1873 return new RawHtml(getLink(new LinkInfoImpl(context, cd,
1874 configuration.getClassName(cd), "")));
1875 }
1877 /**
1878 * Add the class link.
1879 *
1880 * @param context the id of the context where the link will be added
1881 * @param cd the class doc to link to
1882 * @param contentTree the content tree to which the link will be added
1883 */
1884 public void addPreQualifiedClassLink(int context, ClassDoc cd, Content contentTree) {
1885 addPreQualifiedClassLink(context, cd, false, contentTree);
1886 }
1888 /**
1889 * Retrieve the class link with the package portion of the label in
1890 * plain text. If the qualifier is excluded, it willnot be included in the
1891 * link label.
1892 *
1893 * @param cd the class to link to.
1894 * @param isStrong true if the link should be strong.
1895 * @return the link with the package portion of the label in plain text.
1896 */
1897 public String getPreQualifiedClassLink(int context,
1898 ClassDoc cd, boolean isStrong) {
1899 String classlink = "";
1900 PackageDoc pd = cd.containingPackage();
1901 if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
1902 classlink = getPkgName(cd);
1903 }
1904 classlink += getLink(new LinkInfoImpl(context, cd, cd.name(), isStrong));
1905 return classlink;
1906 }
1908 /**
1909 * Add the class link with the package portion of the label in
1910 * plain text. If the qualifier is excluded, it will not be included in the
1911 * link label.
1912 *
1913 * @param context the id of the context where the link will be added
1914 * @param cd the class to link to
1915 * @param isStrong true if the link should be strong
1916 * @param contentTree the content tree to which the link with be added
1917 */
1918 public void addPreQualifiedClassLink(int context,
1919 ClassDoc cd, boolean isStrong, Content contentTree) {
1920 PackageDoc pd = cd.containingPackage();
1921 if(pd != null && ! configuration.shouldExcludeQualifier(pd.name())) {
1922 contentTree.addContent(getPkgName(cd));
1923 }
1924 contentTree.addContent(new RawHtml(getLink(new LinkInfoImpl(
1925 context, cd, cd.name(), isStrong))));
1926 }
1928 /**
1929 * Add the class link, with only class name as the strong link and prefixing
1930 * plain package name.
1931 *
1932 * @param context the id of the context where the link will be added
1933 * @param cd the class to link to
1934 * @param contentTree the content tree to which the link with be added
1935 */
1936 public void addPreQualifiedStrongClassLink(int context, ClassDoc cd, Content contentTree) {
1937 addPreQualifiedClassLink(context, cd, true, contentTree);
1938 }
1940 public void printText(String key) {
1941 print(configuration.getText(key));
1942 }
1944 public void printText(String key, String a1) {
1945 print(configuration.getText(key, a1));
1946 }
1948 public void printText(String key, String a1, String a2) {
1949 print(configuration.getText(key, a1, a2));
1950 }
1952 public void strongText(String key) {
1953 strong(configuration.getText(key));
1954 }
1956 public void strongText(String key, String a1) {
1957 strong(configuration.getText(key, a1));
1958 }
1960 public void strongText(String key, String a1, String a2) {
1961 strong(configuration.getText(key, a1, a2));
1962 }
1964 /**
1965 * Get the link for the given member.
1966 *
1967 * @param context the id of the context where the link will be added
1968 * @param doc the member being linked to
1969 * @param label the label for the link
1970 * @return a content tree for the doc link
1971 */
1972 public Content getDocLink(int context, MemberDoc doc, String label) {
1973 return getDocLink(context, doc.containingClass(), doc, label);
1974 }
1976 /**
1977 * Print the link for the given member.
1978 *
1979 * @param context the id of the context where the link will be printed.
1980 * @param classDoc the classDoc that we should link to. This is not
1981 * necessarily equal to doc.containingClass(). We may be
1982 * inheriting comments.
1983 * @param doc the member being linked to.
1984 * @param label the label for the link.
1985 * @param strong true if the link should be strong.
1986 */
1987 public void printDocLink(int context, ClassDoc classDoc, MemberDoc doc,
1988 String label, boolean strong) {
1989 print(getDocLink(context, classDoc, doc, label, strong));
1990 }
1992 /**
1993 * Return the link for the given member.
1994 *
1995 * @param context the id of the context where the link will be printed.
1996 * @param doc the member being linked to.
1997 * @param label the label for the link.
1998 * @param strong true if the link should be strong.
1999 * @return the link for the given member.
2000 */
2001 public String getDocLink(int context, MemberDoc doc, String label,
2002 boolean strong) {
2003 return getDocLink(context, doc.containingClass(), doc, label, strong);
2004 }
2006 /**
2007 * Return the link for the given member.
2008 *
2009 * @param context the id of the context where the link will be printed.
2010 * @param classDoc the classDoc that we should link to. This is not
2011 * necessarily equal to doc.containingClass(). We may be
2012 * inheriting comments.
2013 * @param doc the member being linked to.
2014 * @param label the label for the link.
2015 * @param strong true if the link should be strong.
2016 * @return the link for the given member.
2017 */
2018 public String getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
2019 String label, boolean strong) {
2020 if (! (doc.isIncluded() ||
2021 Util.isLinkable(classDoc, configuration()))) {
2022 return label;
2023 } else if (doc instanceof ExecutableMemberDoc) {
2024 ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
2025 return getLink(new LinkInfoImpl(context, classDoc,
2026 getAnchor(emd), label, strong));
2027 } else if (doc instanceof MemberDoc) {
2028 return getLink(new LinkInfoImpl(context, classDoc,
2029 doc.name(), label, strong));
2030 } else {
2031 return label;
2032 }
2033 }
2035 /**
2036 * Return the link for the given member.
2037 *
2038 * @param context the id of the context where the link will be added
2039 * @param classDoc the classDoc that we should link to. This is not
2040 * necessarily equal to doc.containingClass(). We may be
2041 * inheriting comments
2042 * @param doc the member being linked to
2043 * @param label the label for the link
2044 * @return the link for the given member
2045 */
2046 public Content getDocLink(int context, ClassDoc classDoc, MemberDoc doc,
2047 String label) {
2048 if (! (doc.isIncluded() ||
2049 Util.isLinkable(classDoc, configuration()))) {
2050 return new StringContent(label);
2051 } else if (doc instanceof ExecutableMemberDoc) {
2052 ExecutableMemberDoc emd = (ExecutableMemberDoc)doc;
2053 return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
2054 getAnchor(emd), label, false)));
2055 } else if (doc instanceof MemberDoc) {
2056 return new RawHtml(getLink(new LinkInfoImpl(context, classDoc,
2057 doc.name(), label, false)));
2058 } else {
2059 return new StringContent(label);
2060 }
2061 }
2063 public void anchor(ExecutableMemberDoc emd) {
2064 anchor(getAnchor(emd));
2065 }
2067 public String getAnchor(ExecutableMemberDoc emd) {
2068 StringBuilder signature = new StringBuilder(emd.signature());
2069 StringBuilder signatureParsed = new StringBuilder();
2070 int counter = 0;
2071 for (int i = 0; i < signature.length(); i++) {
2072 char c = signature.charAt(i);
2073 if (c == '<') {
2074 counter++;
2075 } else if (c == '>') {
2076 counter--;
2077 } else if (counter == 0) {
2078 signatureParsed.append(c);
2079 }
2080 }
2081 return emd.name() + signatureParsed.toString();
2082 }
2084 public String seeTagToString(SeeTag see) {
2085 String tagName = see.name();
2086 if (! (tagName.startsWith("@link") || tagName.equals("@see"))) {
2087 return "";
2088 }
2089 StringBuffer result = new StringBuffer();
2090 boolean isplaintext = tagName.toLowerCase().equals("@linkplain");
2091 String label = see.label();
2092 label = (label.length() > 0)?
2093 ((isplaintext) ? label :
2094 getCode() + label + getCodeEnd()):"";
2095 String seetext = replaceDocRootDir(see.text());
2097 //Check if @see is an href or "string"
2098 if (seetext.startsWith("<") || seetext.startsWith("\"")) {
2099 result.append(seetext);
2100 return result.toString();
2101 }
2103 //The text from the @see tag. We will output this text when a label is not specified.
2104 String text = (isplaintext) ? seetext : getCode() + seetext + getCodeEnd();
2106 ClassDoc refClass = see.referencedClass();
2107 String refClassName = see.referencedClassName();
2108 MemberDoc refMem = see.referencedMember();
2109 String refMemName = see.referencedMemberName();
2110 if (refClass == null) {
2111 //@see is not referencing an included class
2112 PackageDoc refPackage = see.referencedPackage();
2113 if (refPackage != null && refPackage.isIncluded()) {
2114 //@see is referencing an included package
2115 String packageName = isplaintext ? refPackage.name() :
2116 getCode() + refPackage.name() + getCodeEnd();
2117 result.append(getPackageLinkString(refPackage,
2118 label.length() == 0 ? packageName : label, false));
2119 } else {
2120 //@see is not referencing an included class or package. Check for cross links.
2121 String classCrossLink, packageCrossLink = getCrossPackageLink(refClassName);
2122 if (packageCrossLink != null) {
2123 //Package cross link found
2124 result.append(getHyperLinkString(packageCrossLink, "",
2125 (label.length() == 0)? text : label, false));
2126 } else if ((classCrossLink = getCrossClassLink(refClassName,
2127 refMemName, label, false, "", ! isplaintext)) != null) {
2128 //Class cross link found (possiblly to a member in the class)
2129 result.append(classCrossLink);
2130 } else {
2131 //No cross link found so print warning
2132 configuration.getDocletSpecificMsg().warning(see.position(), "doclet.see.class_or_package_not_found",
2133 tagName, seetext);
2134 result.append((label.length() == 0)? text: label);
2135 }
2136 }
2137 } else if (refMemName == null) {
2138 // Must be a class reference since refClass is not null and refMemName is null.
2139 if (label.length() == 0) {
2140 label = (isplaintext) ? refClass.name() : getCode() + refClass.name() + getCodeEnd();
2141 result.append(getLink(new LinkInfoImpl(refClass, label)));
2142 } else {
2143 result.append(getLink(new LinkInfoImpl(refClass, label)));
2144 }
2145 } else if (refMem == null) {
2146 // Must be a member reference since refClass is not null and refMemName is not null.
2147 // However, refMem is null, so this referenced member does not exist.
2148 result.append((label.length() == 0)? text: label);
2149 } else {
2150 // Must be a member reference since refClass is not null and refMemName is not null.
2151 // refMem is not null, so this @see tag must be referencing a valid member.
2152 ClassDoc containing = refMem.containingClass();
2153 if (see.text().trim().startsWith("#") &&
2154 ! (containing.isPublic() ||
2155 Util.isLinkable(containing, configuration()))) {
2156 // Since the link is relative and the holder is not even being
2157 // documented, this must be an inherited link. Redirect it.
2158 // The current class either overrides the referenced member or
2159 // inherits it automatically.
2160 if (this instanceof ClassWriterImpl) {
2161 containing = ((ClassWriterImpl) this).getClassDoc();
2162 } else if (!containing.isPublic()){
2163 configuration.getDocletSpecificMsg().warning(
2164 see.position(), "doclet.see.class_or_package_not_accessible",
2165 tagName, containing.qualifiedName());
2166 } else {
2167 configuration.getDocletSpecificMsg().warning(
2168 see.position(), "doclet.see.class_or_package_not_found",
2169 tagName, seetext);
2170 }
2171 }
2172 if (configuration.currentcd != containing) {
2173 refMemName = containing.name() + "." + refMemName;
2174 }
2175 if (refMem instanceof ExecutableMemberDoc) {
2176 if (refMemName.indexOf('(') < 0) {
2177 refMemName += ((ExecutableMemberDoc)refMem).signature();
2178 }
2179 }
2180 text = (isplaintext) ?
2181 refMemName : getCode() + Util.escapeHtmlChars(refMemName) + getCodeEnd();
2183 result.append(getDocLink(LinkInfoImpl.CONTEXT_SEE_TAG, containing,
2184 refMem, (label.length() == 0)? text: label, false));
2185 }
2186 return result.toString();
2187 }
2189 public void printInlineComment(Doc doc, Tag tag) {
2190 printCommentTags(doc, tag.inlineTags(), false, false);
2191 }
2193 /**
2194 * Add the inline comment.
2195 *
2196 * @param doc the doc for which the inline comment will be added
2197 * @param tag the inline tag to be added
2198 * @param htmltree the content tree to which the comment will be added
2199 */
2200 public void addInlineComment(Doc doc, Tag tag, Content htmltree) {
2201 addCommentTags(doc, tag.inlineTags(), false, false, htmltree);
2202 }
2204 public void printInlineDeprecatedComment(Doc doc, Tag tag) {
2205 printCommentTags(doc, tag.inlineTags(), true, false);
2206 }
2208 /**
2209 * Add the inline deprecated comment.
2210 *
2211 * @param doc the doc for which the inline deprecated comment will be added
2212 * @param tag the inline tag to be added
2213 * @param htmltree the content tree to which the comment will be added
2214 */
2215 public void addInlineDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
2216 addCommentTags(doc, tag.inlineTags(), true, false, htmltree);
2217 }
2219 public void printSummaryComment(Doc doc) {
2220 printSummaryComment(doc, doc.firstSentenceTags());
2221 }
2223 /**
2224 * Adds the summary content.
2225 *
2226 * @param doc the doc for which the summary will be generated
2227 * @param htmltree the documentation tree to which the summary will be added
2228 */
2229 public void addSummaryComment(Doc doc, Content htmltree) {
2230 addSummaryComment(doc, doc.firstSentenceTags(), htmltree);
2231 }
2233 public void printSummaryComment(Doc doc, Tag[] firstSentenceTags) {
2234 printCommentTags(doc, firstSentenceTags, false, true);
2235 }
2237 /**
2238 * Adds the summary content.
2239 *
2240 * @param doc the doc for which the summary will be generated
2241 * @param firstSentenceTags the first sentence tags for the doc
2242 * @param htmltree the documentation tree to which the summary will be added
2243 */
2244 public void addSummaryComment(Doc doc, Tag[] firstSentenceTags, Content htmltree) {
2245 addCommentTags(doc, firstSentenceTags, false, true, htmltree);
2246 }
2248 public void printSummaryDeprecatedComment(Doc doc) {
2249 printCommentTags(doc, doc.firstSentenceTags(), true, true);
2250 }
2252 public void printSummaryDeprecatedComment(Doc doc, Tag tag) {
2253 printCommentTags(doc, tag.firstSentenceTags(), true, true);
2254 }
2256 public void addSummaryDeprecatedComment(Doc doc, Tag tag, Content htmltree) {
2257 addCommentTags(doc, tag.firstSentenceTags(), true, true, htmltree);
2258 }
2260 public void printInlineComment(Doc doc) {
2261 printCommentTags(doc, doc.inlineTags(), false, false);
2262 p();
2263 }
2265 /**
2266 * Adds the inline comment.
2267 *
2268 * @param doc the doc for which the inline comments will be generated
2269 * @param htmltree the documentation tree to which the inline comments will be added
2270 */
2271 public void addInlineComment(Doc doc, Content htmltree) {
2272 addCommentTags(doc, doc.inlineTags(), false, false, htmltree);
2273 }
2275 public void printInlineDeprecatedComment(Doc doc) {
2276 printCommentTags(doc, doc.inlineTags(), true, false);
2277 }
2279 private void printCommentTags(Doc doc, Tag[] tags, boolean depr, boolean first) {
2280 if(configuration.nocomment){
2281 return;
2282 }
2283 if (depr) {
2284 italic();
2285 }
2286 String result = commentTagsToString(null, doc, tags, first);
2287 print(result);
2288 if (depr) {
2289 italicEnd();
2290 }
2291 if (tags.length == 0) {
2292 space();
2293 }
2294 }
2296 /**
2297 * Adds the comment tags.
2298 *
2299 * @param doc the doc for which the comment tags will be generated
2300 * @param tags the first sentence tags for the doc
2301 * @param depr true if it is deprecated
2302 * @param first true if the first sentenge tags should be added
2303 * @param htmltree the documentation tree to which the comment tags will be added
2304 */
2305 private void addCommentTags(Doc doc, Tag[] tags, boolean depr,
2306 boolean first, Content htmltree) {
2307 if(configuration.nocomment){
2308 return;
2309 }
2310 Content div;
2311 Content result = new RawHtml(commentTagsToString(null, doc, tags, first));
2312 if (depr) {
2313 Content italic = HtmlTree.I(result);
2314 div = HtmlTree.DIV(HtmlStyle.block, italic);
2315 htmltree.addContent(div);
2316 }
2317 else {
2318 div = HtmlTree.DIV(HtmlStyle.block, result);
2319 htmltree.addContent(div);
2320 }
2321 if (tags.length == 0) {
2322 htmltree.addContent(getSpace());
2323 }
2324 }
2326 /**
2327 * Converts inline tags and text to text strings, expanding the
2328 * inline tags along the way. Called wherever text can contain
2329 * an inline tag, such as in comments or in free-form text arguments
2330 * to non-inline tags.
2331 *
2332 * @param holderTag specific tag where comment resides
2333 * @param doc specific doc where comment resides
2334 * @param tags array of text tags and inline tags (often alternating)
2335 * present in the text of interest for this doc
2336 * @param isFirstSentence true if text is first sentence
2337 */
2338 public String commentTagsToString(Tag holderTag, Doc doc, Tag[] tags,
2339 boolean isFirstSentence) {
2340 StringBuilder result = new StringBuilder();
2341 boolean textTagChange = false;
2342 // Array of all possible inline tags for this javadoc run
2343 configuration.tagletManager.checkTags(doc, tags, true);
2344 for (int i = 0; i < tags.length; i++) {
2345 Tag tagelem = tags[i];
2346 String tagName = tagelem.name();
2347 if (tagelem instanceof SeeTag) {
2348 result.append(seeTagToString((SeeTag)tagelem));
2349 } else if (! tagName.equals("Text")) {
2350 int originalLength = result.length();
2351 TagletOutput output = TagletWriter.getInlineTagOuput(
2352 configuration.tagletManager, holderTag,
2353 tagelem, getTagletWriterInstance(isFirstSentence));
2354 result.append(output == null ? "" : output.toString());
2355 if (originalLength == 0 && isFirstSentence && tagelem.name().equals("@inheritDoc") && result.length() > 0) {
2356 break;
2357 } else if (configuration.docrootparent.length() > 0 &&
2358 tagelem.name().equals("@docRoot") &&
2359 ((tags[i + 1]).text()).startsWith("/..")) {
2360 //If Xdocrootparent switch ON, set the flag to remove the /.. occurance after
2361 //{@docRoot} tag in the very next Text tag.
2362 textTagChange = true;
2363 continue;
2364 } else {
2365 continue;
2366 }
2367 } else {
2368 String text = tagelem.text();
2369 //If Xdocrootparent switch ON, remove the /.. occurance after {@docRoot} tag.
2370 if (textTagChange) {
2371 text = text.replaceFirst("/..", "");
2372 textTagChange = false;
2373 }
2374 //This is just a regular text tag. The text may contain html links (<a>)
2375 //or inline tag {@docRoot}, which will be handled as special cases.
2376 text = redirectRelativeLinks(tagelem.holder(), text);
2378 // Replace @docRoot only if not represented by an instance of DocRootTaglet,
2379 // that is, only if it was not present in a source file doc comment.
2380 // This happens when inserted by the doclet (a few lines
2381 // above in this method). [It might also happen when passed in on the command
2382 // line as a text argument to an option (like -header).]
2383 text = replaceDocRootDir(text);
2384 if (isFirstSentence) {
2385 text = removeNonInlineHtmlTags(text);
2386 }
2387 StringTokenizer lines = new StringTokenizer(text, "\r\n", true);
2388 StringBuffer textBuff = new StringBuffer();
2389 while (lines.hasMoreTokens()) {
2390 StringBuilder line = new StringBuilder(lines.nextToken());
2391 Util.replaceTabs(configuration.sourcetab, line);
2392 textBuff.append(line.toString());
2393 }
2394 result.append(textBuff);
2395 }
2396 }
2397 return result.toString();
2398 }
2400 /**
2401 * Return true if relative links should not be redirected.
2402 *
2403 * @return Return true if a relative link should not be redirected.
2404 */
2405 private boolean shouldNotRedirectRelativeLinks() {
2406 return this instanceof AnnotationTypeWriter ||
2407 this instanceof ClassWriter ||
2408 this instanceof PackageSummaryWriter;
2409 }
2411 /**
2412 * Suppose a piece of documentation has a relative link. When you copy
2413 * that documetation to another place such as the index or class-use page,
2414 * that relative link will no longer work. We should redirect those links
2415 * so that they will work again.
2416 * <p>
2417 * Here is the algorithm used to fix the link:
2418 * <p>
2419 * {@literal <relative link> => docRoot + <relative path to file> + <relative link> }
2420 * <p>
2421 * For example, suppose com.sun.javadoc.RootDoc has this link:
2422 * {@literal <a href="package-summary.html">The package Page</a> }
2423 * <p>
2424 * If this link appeared in the index, we would redirect
2425 * the link like this:
2426 *
2427 * {@literal <a href="./com/sun/javadoc/package-summary.html">The package Page</a>}
2428 *
2429 * @param doc the Doc object whose documentation is being written.
2430 * @param text the text being written.
2431 *
2432 * @return the text, with all the relative links redirected to work.
2433 */
2434 private String redirectRelativeLinks(Doc doc, String text) {
2435 if (doc == null || shouldNotRedirectRelativeLinks()) {
2436 return text;
2437 }
2439 String redirectPathFromRoot;
2440 if (doc instanceof ClassDoc) {
2441 redirectPathFromRoot = DirectoryManager.getDirectoryPath(((ClassDoc) doc).containingPackage());
2442 } else if (doc instanceof MemberDoc) {
2443 redirectPathFromRoot = DirectoryManager.getDirectoryPath(((MemberDoc) doc).containingPackage());
2444 } else if (doc instanceof PackageDoc) {
2445 redirectPathFromRoot = DirectoryManager.getDirectoryPath((PackageDoc) doc);
2446 } else {
2447 return text;
2448 }
2450 if (! redirectPathFromRoot.endsWith(DirectoryManager.URL_FILE_SEPARATOR)) {
2451 redirectPathFromRoot += DirectoryManager.URL_FILE_SEPARATOR;
2452 }
2454 //Redirect all relative links.
2455 int end, begin = text.toLowerCase().indexOf("<a");
2456 if(begin >= 0){
2457 StringBuffer textBuff = new StringBuffer(text);
2459 while(begin >=0){
2460 if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
2461 begin = textBuff.toString().toLowerCase().indexOf("<a", begin + 1);
2462 continue;
2463 }
2465 begin = textBuff.indexOf("=", begin) + 1;
2466 end = textBuff.indexOf(">", begin +1);
2467 if(begin == 0){
2468 //Link has no equal symbol.
2469 configuration.root.printWarning(
2470 doc.position(),
2471 configuration.getText("doclet.malformed_html_link_tag", text));
2472 break;
2473 }
2474 if (end == -1) {
2475 //Break without warning. This <a> tag is not necessarily malformed. The text
2476 //might be missing '>' character because the href has an inline tag.
2477 break;
2478 }
2479 if(textBuff.substring(begin, end).indexOf("\"") != -1){
2480 begin = textBuff.indexOf("\"", begin) + 1;
2481 end = textBuff.indexOf("\"", begin +1);
2482 if(begin == 0 || end == -1){
2483 //Link is missing a quote.
2484 break;
2485 }
2486 }
2487 String relativeLink = textBuff.substring(begin, end);
2488 if(!(relativeLink.toLowerCase().startsWith("mailto:") ||
2489 relativeLink.toLowerCase().startsWith("http:") ||
2490 relativeLink.toLowerCase().startsWith("https:") ||
2491 relativeLink.toLowerCase().startsWith("file:"))){
2492 relativeLink = "{@"+(new DocRootTaglet()).getName() + "}"
2493 + redirectPathFromRoot
2494 + relativeLink;
2495 textBuff.replace(begin, end, relativeLink);
2496 }
2497 begin = textBuff.toString().toLowerCase().indexOf("<a", begin + 1);
2498 }
2499 return textBuff.toString();
2500 }
2501 return text;
2502 }
2504 public String removeNonInlineHtmlTags(String text) {
2505 if (text.indexOf('<') < 0) {
2506 return text;
2507 }
2508 String noninlinetags[] = { "<ul>", "</ul>", "<ol>", "</ol>",
2509 "<dl>", "</dl>", "<table>", "</table>",
2510 "<tr>", "</tr>", "<td>", "</td>",
2511 "<th>", "</th>", "<p>", "</p>",
2512 "<li>", "</li>", "<dd>", "</dd>",
2513 "<dir>", "</dir>", "<dt>", "</dt>",
2514 "<h1>", "</h1>", "<h2>", "</h2>",
2515 "<h3>", "</h3>", "<h4>", "</h4>",
2516 "<h5>", "</h5>", "<h6>", "</h6>",
2517 "<pre>", "</pre>", "<menu>", "</menu>",
2518 "<listing>", "</listing>", "<hr>",
2519 "<blockquote>", "</blockquote>",
2520 "<center>", "</center>",
2521 "<UL>", "</UL>", "<OL>", "</OL>",
2522 "<DL>", "</DL>", "<TABLE>", "</TABLE>",
2523 "<TR>", "</TR>", "<TD>", "</TD>",
2524 "<TH>", "</TH>", "<P>", "</P>",
2525 "<LI>", "</LI>", "<DD>", "</DD>",
2526 "<DIR>", "</DIR>", "<DT>", "</DT>",
2527 "<H1>", "</H1>", "<H2>", "</H2>",
2528 "<H3>", "</H3>", "<H4>", "</H4>",
2529 "<H5>", "</H5>", "<H6>", "</H6>",
2530 "<PRE>", "</PRE>", "<MENU>", "</MENU>",
2531 "<LISTING>", "</LISTING>", "<HR>",
2532 "<BLOCKQUOTE>", "</BLOCKQUOTE>",
2533 "<CENTER>", "</CENTER>"
2534 };
2535 for (int i = 0; i < noninlinetags.length; i++) {
2536 text = replace(text, noninlinetags[i], "");
2537 }
2538 return text;
2539 }
2541 public String replace(String text, String tobe, String by) {
2542 while (true) {
2543 int startindex = text.indexOf(tobe);
2544 if (startindex < 0) {
2545 return text;
2546 }
2547 int endindex = startindex + tobe.length();
2548 StringBuilder replaced = new StringBuilder();
2549 if (startindex > 0) {
2550 replaced.append(text.substring(0, startindex));
2551 }
2552 replaced.append(by);
2553 if (text.length() > endindex) {
2554 replaced.append(text.substring(endindex));
2555 }
2556 text = replaced.toString();
2557 }
2558 }
2560 public void printStyleSheetProperties() {
2561 String filename = configuration.stylesheetfile;
2562 if (filename.length() > 0) {
2563 File stylefile = new File(filename);
2564 String parent = stylefile.getParent();
2565 filename = (parent == null)?
2566 filename:
2567 filename.substring(parent.length() + 1);
2568 } else {
2569 filename = "stylesheet.css";
2570 }
2571 filename = relativePath + filename;
2572 link("REL =\"stylesheet\" TYPE=\"text/css\" HREF=\"" +
2573 filename + "\" " + "TITLE=\"Style\"");
2574 }
2576 /**
2577 * Returns a link to the stylesheet file.
2578 *
2579 * @return an HtmlTree for the lINK tag which provides the stylesheet location
2580 */
2581 public HtmlTree getStyleSheetProperties() {
2582 String filename = configuration.stylesheetfile;
2583 if (filename.length() > 0) {
2584 File stylefile = new File(filename);
2585 String parent = stylefile.getParent();
2586 filename = (parent == null)?
2587 filename:
2588 filename.substring(parent.length() + 1);
2589 } else {
2590 filename = "stylesheet.css";
2591 }
2592 filename = relativePath + filename;
2593 HtmlTree link = HtmlTree.LINK("stylesheet", "text/css", filename, "Style");
2594 return link;
2595 }
2597 /**
2598 * According to
2599 * <cite>The Java™ Language Specification</cite>,
2600 * all the outer classes and static nested classes are core classes.
2601 */
2602 public boolean isCoreClass(ClassDoc cd) {
2603 return cd.containingClass() == null || cd.isStatic();
2604 }
2606 /**
2607 * Write the annotatation types for the given packageDoc.
2608 *
2609 * @param packageDoc the package to write annotations for.
2610 */
2611 public void writeAnnotationInfo(PackageDoc packageDoc) {
2612 writeAnnotationInfo(packageDoc, packageDoc.annotations());
2613 }
2615 /**
2616 * Adds the annotatation types for the given packageDoc.
2617 *
2618 * @param packageDoc the package to write annotations for.
2619 * @param htmltree the documentation tree to which the annotation info will be
2620 * added
2621 */
2622 public void addAnnotationInfo(PackageDoc packageDoc, Content htmltree) {
2623 addAnnotationInfo(packageDoc, packageDoc.annotations(), htmltree);
2624 }
2626 /**
2627 * Write the annotatation types for the given doc.
2628 *
2629 * @param doc the doc to write annotations for.
2630 */
2631 public void writeAnnotationInfo(ProgramElementDoc doc) {
2632 writeAnnotationInfo(doc, doc.annotations());
2633 }
2635 /**
2636 * Adds the annotatation types for the given doc.
2637 *
2638 * @param packageDoc the package to write annotations for
2639 * @param htmltree the content tree to which the annotation types will be added
2640 */
2641 public void addAnnotationInfo(ProgramElementDoc doc, Content htmltree) {
2642 addAnnotationInfo(doc, doc.annotations(), htmltree);
2643 }
2645 /**
2646 * Write the annotatation types for the given doc and parameter.
2647 *
2648 * @param indent the number of spaced to indent the parameters.
2649 * @param doc the doc to write annotations for.
2650 * @param param the parameter to write annotations for.
2651 */
2652 public boolean writeAnnotationInfo(int indent, Doc doc, Parameter param) {
2653 return writeAnnotationInfo(indent, doc, param.annotations(), false);
2654 }
2656 /**
2657 * Add the annotatation types for the given doc and parameter.
2658 *
2659 * @param indent the number of spaces to indent the parameters.
2660 * @param doc the doc to write annotations for.
2661 * @param param the parameter to write annotations for.
2662 * @param tree the content tree to which the annotation types will be added
2663 */
2664 public boolean addAnnotationInfo(int indent, Doc doc, Parameter param,
2665 Content tree) {
2666 return addAnnotationInfo(indent, doc, param.annotations(), false, tree);
2667 }
2669 /**
2670 * Write the annotatation types for the given doc.
2671 *
2672 * @param doc the doc to write annotations for.
2673 * @param descList the array of {@link AnnotationDesc}.
2674 */
2675 private void writeAnnotationInfo(Doc doc, AnnotationDesc[] descList) {
2676 writeAnnotationInfo(0, doc, descList, true);
2677 }
2679 /**
2680 * Adds the annotatation types for the given doc.
2681 *
2682 * @param doc the doc to write annotations for.
2683 * @param descList the array of {@link AnnotationDesc}.
2684 * @param htmltree the documentation tree to which the annotation info will be
2685 * added
2686 */
2687 private void addAnnotationInfo(Doc doc, AnnotationDesc[] descList,
2688 Content htmltree) {
2689 addAnnotationInfo(0, doc, descList, true, htmltree);
2690 }
2692 /**
2693 * Write the annotatation types for the given doc.
2694 *
2695 * @param indent the number of extra spaces to indent the annotations.
2696 * @param doc the doc to write annotations for.
2697 * @param descList the array of {@link AnnotationDesc}.
2698 */
2699 private boolean writeAnnotationInfo(int indent, Doc doc, AnnotationDesc[] descList, boolean lineBreak) {
2700 List<String> annotations = getAnnotations(indent, descList, lineBreak);
2701 if (annotations.size() == 0) {
2702 return false;
2703 }
2704 fontNoNewLine("-1");
2705 for (Iterator<String> iter = annotations.iterator(); iter.hasNext();) {
2706 print(iter.next());
2707 }
2708 fontEnd();
2709 return true;
2710 }
2712 /**
2713 * Adds the annotatation types for the given doc.
2714 *
2715 * @param indent the number of extra spaces to indent the annotations.
2716 * @param doc the doc to write annotations for.
2717 * @param descList the array of {@link AnnotationDesc}.
2718 * @param htmltree the documentation tree to which the annotation info will be
2719 * added
2720 */
2721 private boolean addAnnotationInfo(int indent, Doc doc,
2722 AnnotationDesc[] descList, boolean lineBreak, Content htmltree) {
2723 List<String> annotations = getAnnotations(indent, descList, lineBreak);
2724 if (annotations.size() == 0) {
2725 return false;
2726 }
2727 Content annotationContent;
2728 for (Iterator<String> iter = annotations.iterator(); iter.hasNext();) {
2729 annotationContent = new RawHtml(iter.next());
2730 htmltree.addContent(annotationContent);
2731 }
2732 return true;
2733 }
2735 /**
2736 * Return the string representations of the annotation types for
2737 * the given doc.
2738 *
2739 * @param indent the number of extra spaces to indent the annotations.
2740 * @param descList the array of {@link AnnotationDesc}.
2741 * @param linkBreak if true, add new line between each member value.
2742 * @return an array of strings representing the annotations being
2743 * documented.
2744 */
2745 private List<String> getAnnotations(int indent, AnnotationDesc[] descList, boolean linkBreak) {
2746 List<String> results = new ArrayList<String>();
2747 StringBuffer annotation;
2748 for (int i = 0; i < descList.length; i++) {
2749 AnnotationTypeDoc annotationDoc = descList[i].annotationType();
2750 if (! Util.isDocumentedAnnotation(annotationDoc)){
2751 continue;
2752 }
2753 annotation = new StringBuffer();
2754 LinkInfoImpl linkInfo = new LinkInfoImpl(
2755 LinkInfoImpl.CONTEXT_ANNOTATION, annotationDoc);
2756 linkInfo.label = "@" + annotationDoc.name();
2757 annotation.append(getLink(linkInfo));
2758 AnnotationDesc.ElementValuePair[] pairs = descList[i].elementValues();
2759 if (pairs.length > 0) {
2760 annotation.append('(');
2761 for (int j = 0; j < pairs.length; j++) {
2762 if (j > 0) {
2763 annotation.append(",");
2764 if (linkBreak) {
2765 annotation.append(DocletConstants.NL);
2766 int spaces = annotationDoc.name().length() + 2;
2767 for (int k = 0; k < (spaces + indent); k++) {
2768 annotation.append(' ');
2769 }
2770 }
2771 }
2772 annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
2773 pairs[j].element(), pairs[j].element().name(), false));
2774 annotation.append('=');
2775 AnnotationValue annotationValue = pairs[j].value();
2776 List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
2777 if (annotationValue.value() instanceof AnnotationValue[]) {
2778 AnnotationValue[] annotationArray =
2779 (AnnotationValue[]) annotationValue.value();
2780 for (int k = 0; k < annotationArray.length; k++) {
2781 annotationTypeValues.add(annotationArray[k]);
2782 }
2783 } else {
2784 annotationTypeValues.add(annotationValue);
2785 }
2786 annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
2787 for (Iterator<AnnotationValue> iter = annotationTypeValues.iterator(); iter.hasNext(); ) {
2788 annotation.append(annotationValueToString(iter.next()));
2789 annotation.append(iter.hasNext() ? "," : "");
2790 }
2791 annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
2792 }
2793 annotation.append(")");
2794 }
2795 annotation.append(linkBreak ? DocletConstants.NL : "");
2796 results.add(annotation.toString());
2797 }
2798 return results;
2799 }
2801 private String annotationValueToString(AnnotationValue annotationValue) {
2802 if (annotationValue.value() instanceof Type) {
2803 Type type = (Type) annotationValue.value();
2804 if (type.asClassDoc() != null) {
2805 LinkInfoImpl linkInfo = new LinkInfoImpl(
2806 LinkInfoImpl.CONTEXT_ANNOTATION, type);
2807 linkInfo.label = (type.asClassDoc().isIncluded() ?
2808 type.typeName() :
2809 type.qualifiedTypeName()) + type.dimension() + ".class";
2810 return getLink(linkInfo);
2811 } else {
2812 return type.typeName() + type.dimension() + ".class";
2813 }
2814 } else if (annotationValue.value() instanceof AnnotationDesc) {
2815 List<String> list = getAnnotations(0,
2816 new AnnotationDesc[]{(AnnotationDesc) annotationValue.value()},
2817 false);
2818 StringBuffer buf = new StringBuffer();
2819 for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
2820 buf.append(iter.next());
2821 }
2822 return buf.toString();
2823 } else if (annotationValue.value() instanceof MemberDoc) {
2824 return getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
2825 (MemberDoc) annotationValue.value(),
2826 ((MemberDoc) annotationValue.value()).name(), false);
2827 } else {
2828 return annotationValue.toString();
2829 }
2830 }
2832 /**
2833 * Return the configuation for this doclet.
2834 *
2835 * @return the configuration for this doclet.
2836 */
2837 public Configuration configuration() {
2838 return configuration;
2839 }
2840 }