< prev index next >

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java

Print this page
rev 47481 : imported patch bhavesh-stylesheets
rev 47482 : 8190295: Introduce a new Table builder class
rev 47483 : 8190818: Introduce a new Script builder class
rev 47484 : 8190819: Merge HtmlWriter into HtmlDocument
rev 47485 : 8190820: Introduce a new Head builder class
rev 47486 : 8190821: Introduce a new Links builder class


  60 import com.sun.source.doctree.IndexTree;
  61 import com.sun.source.doctree.InheritDocTree;
  62 import com.sun.source.doctree.LinkTree;
  63 import com.sun.source.doctree.LiteralTree;
  64 import com.sun.source.doctree.SeeTree;
  65 import com.sun.source.doctree.StartElementTree;
  66 import com.sun.source.doctree.SummaryTree;
  67 import com.sun.source.doctree.TextTree;
  68 import com.sun.source.util.SimpleDocTreeVisitor;
  69 
  70 import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
  71 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  72 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
  73 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
  74 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  75 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocWriter;
  76 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
  77 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  78 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  79 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;

  80 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
  81 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
  82 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  83 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
  84 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
  85 import jdk.javadoc.internal.doclets.toolkit.Content;
  86 import jdk.javadoc.internal.doclets.toolkit.Messages;
  87 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
  88 import jdk.javadoc.internal.doclets.toolkit.Resources;
  89 import jdk.javadoc.internal.doclets.toolkit.taglets.DocRootTaglet;
  90 import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter;
  91 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  92 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
  93 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  94 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
  95 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  96 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  97 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
  98 import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
  99 import jdk.javadoc.internal.doclets.toolkit.util.Utils;


 137 
 138     /**
 139      * Name of the file getting generated. If the file getting generated is
 140      * "java/lang/Object.html", then the filename is "Object.html".
 141      */
 142     public final DocPath filename;
 143 
 144     /**
 145      * The global configuration information for this run.
 146      */
 147     public final HtmlConfiguration configuration;
 148 
 149     protected final Utils utils;
 150 
 151     protected final Contents contents;
 152 
 153     protected final Messages messages;
 154 
 155     protected final Resources resources;
 156 


 157     /**
 158      * To check whether annotation heading is printed or not.
 159      */
 160     protected boolean printedAnnotationHeading = false;
 161 
 162     /**
 163      * To check whether annotation field heading is printed or not.
 164      */
 165     protected boolean printedAnnotationFieldHeading = false;
 166 
 167     /**
 168      * To check whether the repeated annotations is documented or not.
 169      */
 170     private boolean isAnnotationDocumented = false;
 171 
 172     /**
 173      * To check whether the container annotations is documented or not.
 174      */
 175     private boolean isContainerDocumented = false;
 176 


 179     final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*");
 180 
 181     /**
 182      * The window title of this file.
 183      */
 184     protected String winTitle;
 185 
 186     protected Script mainBodyScript;
 187 
 188     /**
 189      * Constructor to construct the HtmlStandardWriter object.
 190      *
 191      * @param path File to be generated.
 192      */
 193     public HtmlDocletWriter(HtmlConfiguration configuration, DocPath path) {
 194         super(configuration, path);
 195         this.configuration = configuration;
 196         this.contents = configuration.contents;
 197         this.messages = configuration.messages;
 198         this.resources = configuration.resources;

 199         this.utils = configuration.utils;
 200         this.path = path;
 201         this.pathToRoot = path.parent().invert();
 202         this.filename = path.basename();
 203     }
 204 
 205     /**
 206      * Replace {@docRoot} tag used in options that accept HTML text, such
 207      * as -header, -footer, -top and -bottom, and when converting a relative
 208      * HREF where commentTagsToString inserts a {@docRoot} where one was
 209      * missing.  (Also see DocRootTaglet for {@docRoot} tags in doc
 210      * comments.)
 211      * <p>
 212      * Replace {@docRoot} tag in htmlstr with the relative path to the
 213      * destination directory from the directory where the file is being
 214      * written, looping to handle all such tags in htmlstr.
 215      * <p>
 216      * For example, for "-d docs" and -header containing {@docRoot}, when
 217      * the HTML page for source file p/C1.java is being generated, the
 218      * {@docRoot} tag would be inserted into the header as "../",


 349 
 350     /**
 351      * Returns a TagletWriter that knows how to write HTML.
 352      *
 353      * @return a TagletWriter that knows how to write HTML.
 354      */
 355     public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
 356         return new TagletWriterImpl(this, isFirstSentence);
 357     }
 358 
 359     /**
 360      * Get Package link, with target frame.
 361      *
 362      * @param pkg The link will be to the "package-summary.html" page for this package
 363      * @param target name of the target frame
 364      * @param label tag for the link
 365      * @return a content for the target package link
 366      */
 367     public Content getTargetPackageLink(PackageElement pkg, String target,
 368             Content label) {
 369         return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
 370     }
 371 
 372     /**
 373      * Get Module Package link, with target frame.
 374      *
 375      * @param pkg the PackageElement
 376      * @param target name of the target frame
 377      * @param label tag for the link
 378      * @param mdle the module being documented
 379      * @return a content for the target module packages link
 380      */
 381     public Content getTargetModulePackageLink(PackageElement pkg, String target,
 382             Content label, ModuleElement mdle) {
 383         return getHyperLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
 384                 label, "", target);
 385     }
 386 
 387     /**
 388      * Get Module link, with target frame.
 389      *
 390      * @param target name of the target frame
 391      * @param label tag for the link
 392      * @param mdle the module being documented
 393      * @return a content for the target module link
 394      */
 395     public Content getTargetModuleLink(String target, Content label, ModuleElement mdle) {
 396         return getHyperLink(pathToRoot.resolve(
 397                 DocPaths.moduleSummary(mdle)), label, "", target);
 398     }
 399 
 400     /**
 401      * Generates the HTML document tree and prints it out.
 402      *
 403      * @param metakeywords Array of String keywords for META tag. Each element
 404      *                     of the array is assigned to a separate META tag.
 405      *                     Pass in null for no array
 406      * @param includeScript true if printing windowtitle script
 407      *                      false for files that appear in the left-hand frames
 408      * @param body the body htmltree to be included in the document
 409      * @throws DocFileIOException if there is a problem writing the file
 410      */
 411     public void printHtmlDocument(List<String> metakeywords, boolean includeScript,
 412             Content body) throws DocFileIOException {
 413         DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
 414         Content htmlComment = contents.newPage;
 415         Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
 416                 .setTimestamp(!configuration.notimestamp)


 483 
 484     /**
 485      * Adds the navigation bar for the Html page at the top and and the bottom.
 486      *
 487      * @param header If true print navigation bar at the top of the page else
 488      * @param htmlTree the HtmlTree to which the nav links will be added
 489      */
 490     protected void addNavLinks(boolean header, Content htmlTree) {
 491         if (!configuration.nonavbar) {
 492             Content tree = (configuration.allowTag(HtmlTag.NAV))
 493                     ? HtmlTree.NAV()
 494                     : htmlTree;
 495             String allClassesId = "allclasses_";
 496             HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
 497             fixedNavDiv.setStyle(HtmlStyle.fixedNav);
 498             Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links");
 499             if (header) {
 500                 fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
 501                 navDiv.setStyle(HtmlStyle.topNav);
 502                 allClassesId += "navbar_top";
 503                 Content a = getMarkerAnchor(SectionName.NAVBAR_TOP);
 504                 //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
 505                 navDiv.addContent(a);
 506                 Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
 507                     getDocLink(SectionName.SKIP_NAVBAR_TOP), skipNavLinks,
 508                     skipNavLinks.toString(), ""));
 509                 navDiv.addContent(skipLinkContent);
 510             } else {
 511                 tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
 512                 navDiv.setStyle(HtmlStyle.bottomNav);
 513                 allClassesId += "navbar_bottom";
 514                 Content a = getMarkerAnchor(SectionName.NAVBAR_BOTTOM);
 515                 navDiv.addContent(a);
 516                 Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
 517                     getDocLink(SectionName.SKIP_NAVBAR_BOTTOM), skipNavLinks,
 518                     skipNavLinks.toString(), ""));
 519                 navDiv.addContent(skipLinkContent);
 520             }
 521             if (header) {
 522                 navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
 523             } else {
 524                 navDiv.addContent(getMarkerAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
 525             }
 526             HtmlTree navList = new HtmlTree(HtmlTag.UL);
 527             navList.setStyle(HtmlStyle.navList);
 528             navList.addAttr(HtmlAttr.TITLE,
 529                             configuration.getText("doclet.Navigation"));
 530             if (configuration.createoverview) {
 531                 navList.addContent(getNavLinkContents());
 532             }
 533             if (configuration.showModules) {
 534                 if (configuration.modules.size() == 1) {
 535                     navList.addContent(getNavLinkModule(configuration.modules.first()));
 536                 } else if (!configuration.modules.isEmpty()) {
 537                     navList.addContent(getNavLinkModule());
 538                 }
 539             }
 540             if (configuration.packages.size() == 1) {
 541                 navList.addContent(getNavLinkPackage(configuration.packages.first()));
 542             } else if (!configuration.packages.isEmpty()) {
 543                 navList.addContent(getNavLinkPackage());
 544             }


 575                 subDiv.addContent(ulFrames);
 576             }
 577             HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
 578             ulAllClasses.addAttr(HtmlAttr.ID, allClassesId);
 579             subDiv.addContent(ulAllClasses);
 580             if (header && configuration.createindex) {
 581                 String searchValueId = "search";
 582                 String reset = "reset";
 583                 HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId);
 584                 HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset);
 585                 Content searchTxt = configuration.getContent("doclet.search");
 586                 HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchTxt));
 587                 liInput.addContent(inputText);
 588                 liInput.addContent(inputReset);
 589                 HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput);
 590                 subDiv.addContent(ulSearch);
 591             }
 592             subDiv.addContent(getAllClassesLinkScript(allClassesId));
 593             addSummaryDetailLinks(subDiv);
 594             if (header) {
 595                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_TOP));
 596                 fixedNavDiv.addContent(subDiv);
 597                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
 598                 tree.addContent(fixedNavDiv);
 599                 HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE);
 600                 tree.addContent(paddingDiv);
 601                 Script script = new Script(
 602                         "<!--\n"
 603                         + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
 604                         + "//-->\n");
 605                 tree.addContent(script.asContent());
 606             } else {
 607                 subDiv.addContent(getMarkerAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
 608                 tree.addContent(subDiv);
 609                 tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
 610             }
 611             if (configuration.allowTag(HtmlTag.NAV)) {
 612                 htmlTree.addContent(tree);
 613             }
 614         }
 615     }
 616 
 617     /**
 618      * Get the word "NEXT" to indicate that no link is available.  Override
 619      * this method to customize next link.
 620      *
 621      * @return a content tree for the link
 622      */
 623     protected Content getNavLinkNext() {
 624         return getNavLinkNext(null);
 625     }
 626 
 627     /**


 629      * this method to customize prev link.
 630      *
 631      * @return a content tree for the link
 632      */
 633     protected Content getNavLinkPrevious() {
 634         return getNavLinkPrevious(null);
 635     }
 636 
 637     /**
 638      * Do nothing. This is the default method.
 639      */
 640     protected void addSummaryDetailLinks(Content navDiv) {
 641     }
 642 
 643     /**
 644      * Get link to the "overview-summary.html" page.
 645      *
 646      * @return a content tree for the link
 647      */
 648     protected Content getNavLinkContents() {
 649         Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
 650                 contents.overviewLabel, "", "");
 651         Content li = HtmlTree.LI(linkContent);
 652         return li;
 653     }
 654 
 655     /**
 656      * Get link to the module summary page for the module passed.
 657      *
 658      * @param mdle Module to which link will be generated
 659      * @return a content tree for the link
 660      */
 661     protected Content getNavLinkModule(ModuleElement mdle) {
 662         Content linkContent = getModuleLink(mdle, contents.moduleLabel);
 663         Content li = HtmlTree.LI(linkContent);
 664         return li;
 665     }
 666 
 667     /**
 668      * Get the word "Module", to indicate that link is not available here.
 669      *


 698 
 699     /**
 700      * Get the word "Use", to indicate that link is not available.
 701      *
 702      * @return a content tree for the link
 703      */
 704     protected Content getNavLinkClassUse() {
 705         Content li = HtmlTree.LI(contents.useLabel);
 706         return li;
 707     }
 708 
 709     /**
 710      * Get link for previous file.
 711      *
 712      * @param prev File name for the prev link
 713      * @return a content tree for the link
 714      */
 715     public Content getNavLinkPrevious(DocPath prev) {
 716         Content li;
 717         if (prev != null) {
 718             li = HtmlTree.LI(getHyperLink(prev, contents.prevLabel, "", ""));
 719         }
 720         else
 721             li = HtmlTree.LI(contents.prevLabel);
 722         return li;
 723     }
 724 
 725     /**
 726      * Get link for next file.  If next is null, just print the label
 727      * without linking it anywhere.
 728      *
 729      * @param next File name for the next link
 730      * @return a content tree for the link
 731      */
 732     public Content getNavLinkNext(DocPath next) {
 733         Content li;
 734         if (next != null) {
 735             li = HtmlTree.LI(getHyperLink(next, contents.nextLabel, "", ""));
 736         }
 737         else
 738             li = HtmlTree.LI(contents.nextLabel);
 739         return li;
 740     }
 741 
 742     /**
 743      * Get "FRAMES" link, to switch to the frame version of the output.
 744      *
 745      * @param link File to be linked, "index.html"
 746      * @return a content tree for the link
 747      */
 748     protected Content getNavShowLists(DocPath link) {
 749         DocLink dl = new DocLink(link, path.getPath(), null);
 750         Content framesContent = getHyperLink(dl, contents.framesLabel, "", "_top");
 751         Content li = HtmlTree.LI(framesContent);
 752         return li;
 753     }
 754 
 755     /**
 756      * Get "FRAMES" link, to switch to the frame version of the output.
 757      *
 758      * @return a content tree for the link
 759      */
 760     protected Content getNavShowLists() {
 761         return getNavShowLists(pathToRoot.resolve(DocPaths.INDEX));
 762     }
 763 
 764     /**
 765      * Get "NO FRAMES" link, to switch to the non-frame version of the output.
 766      *
 767      * @param link File to be linked
 768      * @return a content tree for the link
 769      */
 770     protected Content getNavHideLists(DocPath link) {
 771         Content noFramesContent = getHyperLink(link, contents.noFramesLabel, "", "_top");
 772         Content li = HtmlTree.LI(noFramesContent);
 773         return li;
 774     }
 775 
 776     /**
 777      * Get "Tree" link in the navigation bar. If there is only one package
 778      * specified on the command line, then the "Tree" link will be to the
 779      * only "package-tree.html" file otherwise it will be to the
 780      * "overview-tree.html" file.
 781      *
 782      * @return a content tree for the link
 783      */
 784     protected Content getNavLinkTree() {
 785         List<PackageElement> packages = new ArrayList<>(configuration.getSpecifiedPackageElements());
 786         DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty()
 787                 ? pathString(packages.get(0), DocPaths.PACKAGE_TREE)
 788                 : pathToRoot.resolve(DocPaths.OVERVIEW_TREE);
 789         return HtmlTree.LI(getHyperLink(docPath, contents.treeLabel, "", ""));
 790     }
 791 
 792     /**
 793      * Get the overview tree link for the main tree.
 794      *
 795      * @param label the label for the link
 796      * @return a content tree for the link
 797      */
 798     protected Content getNavLinkMainTree(String label) {
 799         Content mainTreeContent = getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
 800                 new StringContent(label));
 801         Content li = HtmlTree.LI(mainTreeContent);
 802         return li;
 803     }
 804 
 805     /**
 806      * Get the word "Class", to indicate that class link is not available.
 807      *
 808      * @return a content tree for the link
 809      */
 810     protected Content getNavLinkClass() {
 811         Content li = HtmlTree.LI(contents.classLabel);
 812         return li;
 813     }
 814 
 815     /**
 816      * Get "Deprecated" API link in the navigation bar.
 817      *
 818      * @return a content tree for the link
 819      */
 820     protected Content getNavLinkDeprecated() {
 821         Content linkContent = getHyperLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
 822                 contents.deprecatedLabel, "", "");
 823         Content li = HtmlTree.LI(linkContent);
 824         return li;
 825     }
 826 
 827     /**
 828      * Get link for generated index. If the user has used "-splitindex"
 829      * command line option, then link to file "index-files/index-1.html" is
 830      * generated otherwise link to file "index-all.html" is generated.
 831      *
 832      * @return a content tree for the link
 833      */
 834     protected Content getNavLinkClassIndex() {
 835         Content allClassesContent = getHyperLink(pathToRoot.resolve(
 836                 DocPaths.AllClasses(configuration.frames)),
 837                 contents.allClassesLabel, "", "");
 838         Content li = HtmlTree.LI(allClassesContent);
 839         return li;
 840     }
 841 
 842     /**
 843      * Get link for generated class index.
 844      *
 845      * @return a content tree for the link
 846      */
 847     protected Content getNavLinkIndex() {
 848         Content linkContent = getHyperLink(pathToRoot.resolve(
 849                 (configuration.splitindex
 850                     ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1))
 851                     : DocPaths.INDEX_ALL)),
 852             contents.indexLabel, "", "");
 853         Content li = HtmlTree.LI(linkContent);
 854         return li;
 855     }
 856 
 857     /**
 858      * Get help file link. If user has provided a help file, then generate a
 859      * link to the user given file, which is already copied to current or
 860      * destination directory.
 861      *
 862      * @return a content tree for the link
 863      */
 864     protected Content getNavLinkHelp() {
 865         String helpfile = configuration.helpfile;
 866         DocPath helpfilenm;
 867         if (helpfile.isEmpty()) {
 868             helpfilenm = DocPaths.HELP_DOC;
 869         } else {
 870             DocFile file = DocFile.createFileForInput(configuration, helpfile);
 871             helpfilenm = DocPath.create(file.getName());
 872         }
 873         Content linkContent = getHyperLink(pathToRoot.resolve(helpfilenm),
 874                 contents.helpLabel, "", "");
 875         Content li = HtmlTree.LI(linkContent);
 876         return li;
 877     }
 878 
 879     /**
 880      * Add gap between navigation bar elements.
 881      *
 882      * @param liNav the content tree to which the gap will be added
 883      */
 884     protected void addNavGap(Content liNav) {
 885         liNav.addContent(Contents.SPACE);
 886         liNav.addContent("|");
 887         liNav.addContent(Contents.SPACE);
 888     }
 889 
 890     /**
 891      * Get table caption.
 892      *
 893      * @param title the content for the caption
 894      * @return a content tree for the caption
 895      */
 896     public Content getTableCaption(Content title) {
 897         Content captionSpan = HtmlTree.SPAN(title);
 898         Content space = Contents.SPACE;
 899         Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
 900         Content caption = HtmlTree.CAPTION(captionSpan);
 901         caption.addContent(tabSpan);
 902         return caption;
 903     }
 904 
 905     /**
 906      * Get the marker anchor which will be added to the documentation tree.
 907      *
 908      * @param anchorName the anchor name attribute
 909      * @return a content tree for the marker anchor
 910      */
 911     public Content getMarkerAnchor(String anchorName) {
 912         return getMarkerAnchor(getName(anchorName), null);
 913     }
 914 
 915     /**
 916      * Get the marker anchor which will be added to the documentation tree.
 917      *
 918      * @param sectionName the section name anchor attribute for page
 919      * @return a content tree for the marker anchor
 920      */
 921     public Content getMarkerAnchor(SectionName sectionName) {
 922         return getMarkerAnchor(sectionName.getName(), null);
 923     }
 924 
 925     /**
 926      * Get the marker anchor which will be added to the documentation tree.
 927      *
 928      * @param sectionName the section name anchor attribute for page
 929      * @param anchorName the anchor name combined with section name attribute for the page
 930      * @return a content tree for the marker anchor
 931      */
 932     public Content getMarkerAnchor(SectionName sectionName, String anchorName) {
 933         return getMarkerAnchor(sectionName.getName() + getName(anchorName), null);
 934     }
 935 
 936     /**
 937      * Get the marker anchor which will be added to the documentation tree.
 938      *
 939      * @param anchorName the anchor name or id attribute
 940      * @param anchorContent the content that should be added to the anchor
 941      * @return a content tree for the marker anchor
 942      */
 943     public Content getMarkerAnchor(String anchorName, Content anchorContent) {
 944         if (anchorContent == null)
 945             anchorContent = new Comment(" ");
 946         Content markerAnchor = HtmlTree.A(configuration.htmlVersion, anchorName, anchorContent);
 947         return markerAnchor;
 948     }
 949 
 950     /**
 951      * Returns a packagename content.
 952      *
 953      * @param packageElement the package to check
 954      * @return package name content
 955      */
 956     public Content getPackageName(PackageElement packageElement) {
 957         return packageElement == null || packageElement.isUnnamed()
 958                 ? contents.defaultPackageLabel
 959                 : getPackageLabel(packageElement.getQualifiedName());
 960     }
 961 
 962     /**
 963      * Returns a package name label.
 964      *
 965      * @param packageName the package name
 966      * @return the package name content
 967      */
 968     public Content getPackageLabel(CharSequence packageName) {
 969         return new StringContent(packageName);
 970     }


1022     }
1023 
1024     /**
1025      * Return the link to the given package.
1026      *
1027      * @param packageElement the package to link to.
1028      * @param label the label for the link.
1029      * @return a content tree for the package link.
1030      */
1031     public Content getPackageLink(PackageElement packageElement, Content label) {
1032         boolean included = packageElement != null && utils.isIncluded(packageElement);
1033         if (!included) {
1034             for (PackageElement p : configuration.packages) {
1035                 if (p.equals(packageElement)) {
1036                     included = true;
1037                     break;
1038                 }
1039             }
1040         }
1041         if (included || packageElement == null) {
1042             return getHyperLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
1043                     label);
1044         } else {
1045             DocLink crossPkgLink = getCrossPackageLink(utils.getPackageName(packageElement));
1046             if (crossPkgLink != null) {
1047                 return getHyperLink(crossPkgLink, label);
1048             } else {
1049                 return label;
1050             }
1051         }
1052     }
1053 
1054     /**
1055      * Get Module link.
1056      *
1057      * @param mdle the module being documented
1058      * @param label tag for the link
1059      * @return a content for the module link
1060      */
1061     public Content getModuleLink(ModuleElement mdle, Content label) {
1062         boolean included = utils.isIncluded(mdle);
1063         return (included)
1064                 ? getHyperLink(pathToRoot.resolve(DocPaths.moduleSummary(mdle)), label, "", "")
1065                 : label;
1066     }
1067 
1068     public Content interfaceName(TypeElement typeElement, boolean qual) {
1069         Content name = new StringContent((qual)
1070                 ? typeElement.getQualifiedName()
1071                 : utils.getSimpleName(typeElement));
1072         return (utils.isInterface(typeElement)) ?  HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name;
1073     }
1074 
1075     /**
1076      * Add the link to the content tree.
1077      *
1078      * @param typeElement program element typeElement for which the link will be added
1079      * @param label label for the link
1080      * @param htmltree the content tree to which the link will be added
1081      */
1082     public void addSrcLink(Element typeElement, Content label, Content htmltree) {
1083         if (typeElement == null) {
1084             return;
1085         }
1086         TypeElement te = utils.getEnclosingTypeElement(typeElement);
1087         if (te == null) {
1088             // must be a typeElement since in has no containing class.
1089             te = (TypeElement) typeElement;
1090         }
1091         DocPath href = pathToRoot
1092                 .resolve(DocPaths.SOURCE_OUTPUT)
1093                 .resolve(DocPath.forClass(utils, te));
1094         Content linkContent = getHyperLink(href
1095                 .fragment(SourceToHTMLConverter.getAnchorName(utils, typeElement)), label, "", "");
1096         htmltree.addContent(linkContent);
1097     }
1098 
1099     /**
1100      * Return the link to the given class.
1101      *
1102      * @param linkInfo the information about the link.
1103      *
1104      * @return the link for the given class.
1105      */
1106     public Content getLink(LinkInfoImpl linkInfo) {
1107         LinkFactoryImpl factory = new LinkFactoryImpl(this);
1108         return factory.getLink(linkInfo);
1109     }
1110 
1111     /**
1112      * Return the type parameters for the given class.
1113      *
1114      * @param linkInfo the information about the link.


1139         String className = "";
1140         String packageName = qualifiedClassName == null ? "" : qualifiedClassName;
1141         int periodIndex;
1142         while ((periodIndex = packageName.lastIndexOf('.')) != -1) {
1143             className = packageName.substring(periodIndex + 1, packageName.length()) +
1144                 (className.length() > 0 ? "." + className : "");
1145             Content defaultLabel = new StringContent(className);
1146             if (code)
1147                 defaultLabel = HtmlTree.CODE(defaultLabel);
1148             packageName = packageName.substring(0, periodIndex);
1149             if (getCrossPackageLink(packageName) != null) {
1150                 /*
1151                 The package exists in external documentation, so link to the external
1152                 class (assuming that it exists).  This is definitely a limitation of
1153                 the -link option.  There are ways to determine if an external package
1154                 exists, but no way to determine if the external class exists.  We just
1155                 have to assume that it does.
1156                 */
1157                 DocLink link = configuration.extern.getExternalLink(packageName, pathToRoot,
1158                                 className + ".html", refMemName);
1159                 return getHyperLink(link,
1160                     (label == null) || label.isEmpty() ? defaultLabel : label,
1161                     strong, style,
1162                     configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
1163                     "");
1164             }
1165         }
1166         return null;
1167     }
1168 
1169     public boolean isClassLinkable(TypeElement typeElement) {
1170         if (utils.isIncluded(typeElement)) {
1171             return configuration.isGeneratedDoc(typeElement);
1172         }
1173         return configuration.extern.isExternal(typeElement);
1174     }
1175 
1176     public DocLink getCrossPackageLink(String pkgName) {
1177         return configuration.extern.getExternalLink(pkgName, pathToRoot,
1178             DocPaths.PACKAGE_SUMMARY.getPath());
1179     }


1323             CharSequence label, boolean strong, boolean isProperty) {
1324         return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty);
1325     }
1326 
1327     CharSequence check(CharSequence s) {
1328         Matcher m = IMPROPER_HTML_CHARS.matcher(s);
1329         if (m.matches()) {
1330             throw new IllegalArgumentException(s.toString());
1331         }
1332         return s;
1333     }
1334 
1335     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
1336             Content label, boolean strong, boolean isProperty) {
1337         if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) {
1338             return label;
1339         } else if (utils.isExecutableElement(element)) {
1340             ExecutableElement ee = (ExecutableElement)element;
1341             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1342                 .label(label)
1343                 .where(getName(getAnchor(ee, isProperty)))
1344                 .strong(strong));
1345         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
1346             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1347                 .label(label)
1348                 .where(getName(element.getSimpleName().toString()))
1349                 .strong(strong));
1350         } else {
1351             return label;
1352         }
1353     }
1354 
1355     /**
1356      * Return the link for the given member.
1357      *
1358      * @param context the id of the context where the link will be added
1359      * @param typeElement the typeElement that we should link to.  This is not
1360                  necessarily equal to element.containingClass().  We may be
1361                  inheriting comments
1362      * @param element the member being linked to
1363      * @param label the label for the link
1364      * @return the link for the given member
1365      */
1366     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
1367             Content label) {
1368         if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) {
1369             return label;
1370         } else if (utils.isExecutableElement(element)) {
1371             ExecutableElement emd = (ExecutableElement) element;
1372             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1373                 .label(label)
1374                 .where(getName(getAnchor(emd))));
1375         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
1376             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1377                 .label(label).where(getName(element.getSimpleName().toString())));
1378         } else {
1379             return label;
1380         }
1381     }
1382 
1383     public String getAnchor(ExecutableElement executableElement) {
1384         return getAnchor(executableElement, false);
1385     }
1386 
1387     public String getAnchor(ExecutableElement executableElement, boolean isProperty) {
1388         if (isProperty) {
1389             return executableElement.getSimpleName().toString();
1390         }
1391         String member = anchorName(executableElement);
1392         String erasedSignature = utils.makeSignature(executableElement, true, true);
1393         return member + erasedSignature;
1394     }
1395 
1396     public String anchorName(Element member) {
1397         if (member.getKind() == ElementKind.CONSTRUCTOR


1428         String refMemName =    ch.getReferencedMemberName(see);
1429 
1430         if (refMemName == null && refMem != null) {
1431             refMemName = refMem.toString();
1432         }
1433         if (refClass == null) {
1434             //@see is not referencing an included class
1435             PackageElement refPackage = ch.getReferencedPackage(configuration, see);
1436             if (refPackage != null && utils.isIncluded(refPackage)) {
1437                 //@see is referencing an included package
1438                 if (label.isEmpty())
1439                     label = plainOrCode(isLinkPlain,
1440                             new StringContent(refPackage.getQualifiedName()));
1441                 return getPackageLink(refPackage, label);
1442             } else {
1443                 // @see is not referencing an included class or package.  Check for cross links.
1444                 Content classCrossLink;
1445                 DocLink packageCrossLink = getCrossPackageLink(refClassName);
1446                 if (packageCrossLink != null) {
1447                     // Package cross link found
1448                     return getHyperLink(packageCrossLink,
1449                         (label.isEmpty() ? text : label));
1450                 } else if ((classCrossLink = getCrossClassLink(refClassName,
1451                         refMemName, label, false, "", !isLinkPlain)) != null) {
1452                     // Class cross link found (possibly to a member in the class)
1453                     return classCrossLink;
1454                 } else {
1455                     // No cross link found so print warning
1456                     messages.warning(ch.getDocTreePath(see),
1457                             "doclet.see.class_or_package_not_found",
1458                             "@" + tagName,
1459                             seetext);
1460                     return (label.isEmpty() ? text: label);
1461                 }
1462             }
1463         } else if (refMemName == null) {
1464             // Must be a class reference since refClass is not null and refMemName is null.
1465             if (label.isEmpty()) {
1466                 /*
1467                  * it seems to me this is the right thing to do, but it causes comparator failures.
1468                  */




  60 import com.sun.source.doctree.IndexTree;
  61 import com.sun.source.doctree.InheritDocTree;
  62 import com.sun.source.doctree.LinkTree;
  63 import com.sun.source.doctree.LiteralTree;
  64 import com.sun.source.doctree.SeeTree;
  65 import com.sun.source.doctree.StartElementTree;
  66 import com.sun.source.doctree.SummaryTree;
  67 import com.sun.source.doctree.TextTree;
  68 import com.sun.source.util.SimpleDocTreeVisitor;
  69 
  70 import jdk.javadoc.internal.doclets.formats.html.markup.Comment;
  71 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  72 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
  73 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
  74 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  75 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocWriter;
  76 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
  77 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  78 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  79 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  80 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
  81 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
  82 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
  83 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  84 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
  85 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
  86 import jdk.javadoc.internal.doclets.toolkit.Content;
  87 import jdk.javadoc.internal.doclets.toolkit.Messages;
  88 import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
  89 import jdk.javadoc.internal.doclets.toolkit.Resources;
  90 import jdk.javadoc.internal.doclets.toolkit.taglets.DocRootTaglet;
  91 import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter;
  92 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  93 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
  94 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  95 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
  96 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  97 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  98 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
  99 import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
 100 import jdk.javadoc.internal.doclets.toolkit.util.Utils;


 138 
 139     /**
 140      * Name of the file getting generated. If the file getting generated is
 141      * "java/lang/Object.html", then the filename is "Object.html".
 142      */
 143     public final DocPath filename;
 144 
 145     /**
 146      * The global configuration information for this run.
 147      */
 148     public final HtmlConfiguration configuration;
 149 
 150     protected final Utils utils;
 151 
 152     protected final Contents contents;
 153 
 154     protected final Messages messages;
 155 
 156     protected final Resources resources;
 157 
 158     protected final Links links;
 159 
 160     /**
 161      * To check whether annotation heading is printed or not.
 162      */
 163     protected boolean printedAnnotationHeading = false;
 164 
 165     /**
 166      * To check whether annotation field heading is printed or not.
 167      */
 168     protected boolean printedAnnotationFieldHeading = false;
 169 
 170     /**
 171      * To check whether the repeated annotations is documented or not.
 172      */
 173     private boolean isAnnotationDocumented = false;
 174 
 175     /**
 176      * To check whether the container annotations is documented or not.
 177      */
 178     private boolean isContainerDocumented = false;
 179 


 182     final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*");
 183 
 184     /**
 185      * The window title of this file.
 186      */
 187     protected String winTitle;
 188 
 189     protected Script mainBodyScript;
 190 
 191     /**
 192      * Constructor to construct the HtmlStandardWriter object.
 193      *
 194      * @param path File to be generated.
 195      */
 196     public HtmlDocletWriter(HtmlConfiguration configuration, DocPath path) {
 197         super(configuration, path);
 198         this.configuration = configuration;
 199         this.contents = configuration.contents;
 200         this.messages = configuration.messages;
 201         this.resources = configuration.resources;
 202         this.links = configuration.links;
 203         this.utils = configuration.utils;
 204         this.path = path;
 205         this.pathToRoot = path.parent().invert();
 206         this.filename = path.basename();
 207     }
 208 
 209     /**
 210      * Replace {@docRoot} tag used in options that accept HTML text, such
 211      * as -header, -footer, -top and -bottom, and when converting a relative
 212      * HREF where commentTagsToString inserts a {@docRoot} where one was
 213      * missing.  (Also see DocRootTaglet for {@docRoot} tags in doc
 214      * comments.)
 215      * <p>
 216      * Replace {@docRoot} tag in htmlstr with the relative path to the
 217      * destination directory from the directory where the file is being
 218      * written, looping to handle all such tags in htmlstr.
 219      * <p>
 220      * For example, for "-d docs" and -header containing {@docRoot}, when
 221      * the HTML page for source file p/C1.java is being generated, the
 222      * {@docRoot} tag would be inserted into the header as "../",


 353 
 354     /**
 355      * Returns a TagletWriter that knows how to write HTML.
 356      *
 357      * @return a TagletWriter that knows how to write HTML.
 358      */
 359     public TagletWriter getTagletWriterInstance(boolean isFirstSentence) {
 360         return new TagletWriterImpl(this, isFirstSentence);
 361     }
 362 
 363     /**
 364      * Get Package link, with target frame.
 365      *
 366      * @param pkg The link will be to the "package-summary.html" page for this package
 367      * @param target name of the target frame
 368      * @param label tag for the link
 369      * @return a content for the target package link
 370      */
 371     public Content getTargetPackageLink(PackageElement pkg, String target,
 372             Content label) {
 373         return Links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY), label, "", target);
 374     }
 375 
 376     /**
 377      * Get Module Package link, with target frame.
 378      *
 379      * @param pkg the PackageElement
 380      * @param target name of the target frame
 381      * @param label tag for the link
 382      * @param mdle the module being documented
 383      * @return a content for the target module packages link
 384      */
 385     public Content getTargetModulePackageLink(PackageElement pkg, String target,
 386             Content label, ModuleElement mdle) {
 387         return Links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
 388                 label, "", target);
 389     }
 390 
 391     /**
 392      * Get Module link, with target frame.
 393      *
 394      * @param target name of the target frame
 395      * @param label tag for the link
 396      * @param mdle the module being documented
 397      * @return a content for the target module link
 398      */
 399     public Content getTargetModuleLink(String target, Content label, ModuleElement mdle) {
 400         return Links.createLink(pathToRoot.resolve(
 401                 DocPaths.moduleSummary(mdle)), label, "", target);
 402     }
 403 
 404     /**
 405      * Generates the HTML document tree and prints it out.
 406      *
 407      * @param metakeywords Array of String keywords for META tag. Each element
 408      *                     of the array is assigned to a separate META tag.
 409      *                     Pass in null for no array
 410      * @param includeScript true if printing windowtitle script
 411      *                      false for files that appear in the left-hand frames
 412      * @param body the body htmltree to be included in the document
 413      * @throws DocFileIOException if there is a problem writing the file
 414      */
 415     public void printHtmlDocument(List<String> metakeywords, boolean includeScript,
 416             Content body) throws DocFileIOException {
 417         DocType htmlDocType = DocType.forVersion(configuration.htmlVersion);
 418         Content htmlComment = contents.newPage;
 419         Head head = new Head(path, configuration.htmlVersion, configuration.docletVersion)
 420                 .setTimestamp(!configuration.notimestamp)


 487 
 488     /**
 489      * Adds the navigation bar for the Html page at the top and and the bottom.
 490      *
 491      * @param header If true print navigation bar at the top of the page else
 492      * @param htmlTree the HtmlTree to which the nav links will be added
 493      */
 494     protected void addNavLinks(boolean header, Content htmlTree) {
 495         if (!configuration.nonavbar) {
 496             Content tree = (configuration.allowTag(HtmlTag.NAV))
 497                     ? HtmlTree.NAV()
 498                     : htmlTree;
 499             String allClassesId = "allclasses_";
 500             HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
 501             fixedNavDiv.setStyle(HtmlStyle.fixedNav);
 502             Content skipNavLinks = configuration.getContent("doclet.Skip_navigation_links");
 503             if (header) {
 504                 fixedNavDiv.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
 505                 navDiv.setStyle(HtmlStyle.topNav);
 506                 allClassesId += "navbar_top";
 507                 Content a = links.createAnchor(SectionName.NAVBAR_TOP);
 508                 //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
 509                 navDiv.addContent(a);
 510                 Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav,
 511                         Links.createLink(SectionName.SKIP_NAVBAR_TOP, skipNavLinks,
 512                         skipNavLinks.toString(), ""));
 513                 navDiv.addContent(skipLinkContent);
 514             } else {
 515                 tree.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
 516                 navDiv.setStyle(HtmlStyle.bottomNav);
 517                 allClassesId += "navbar_bottom";
 518                 Content a = links.createAnchor(SectionName.NAVBAR_BOTTOM);
 519                 navDiv.addContent(a);
 520                 Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav,
 521                         Links.createLink(SectionName.SKIP_NAVBAR_BOTTOM, skipNavLinks,
 522                         skipNavLinks.toString(), ""));
 523                 navDiv.addContent(skipLinkContent);
 524             }
 525             if (header) {
 526                 navDiv.addContent(links.createAnchor(SectionName.NAVBAR_TOP_FIRSTROW));
 527             } else {
 528                 navDiv.addContent(links.createAnchor(SectionName.NAVBAR_BOTTOM_FIRSTROW));
 529             }
 530             HtmlTree navList = new HtmlTree(HtmlTag.UL);
 531             navList.setStyle(HtmlStyle.navList);
 532             navList.addAttr(HtmlAttr.TITLE,
 533                             configuration.getText("doclet.Navigation"));
 534             if (configuration.createoverview) {
 535                 navList.addContent(getNavLinkContents());
 536             }
 537             if (configuration.showModules) {
 538                 if (configuration.modules.size() == 1) {
 539                     navList.addContent(getNavLinkModule(configuration.modules.first()));
 540                 } else if (!configuration.modules.isEmpty()) {
 541                     navList.addContent(getNavLinkModule());
 542                 }
 543             }
 544             if (configuration.packages.size() == 1) {
 545                 navList.addContent(getNavLinkPackage(configuration.packages.first()));
 546             } else if (!configuration.packages.isEmpty()) {
 547                 navList.addContent(getNavLinkPackage());
 548             }


 579                 subDiv.addContent(ulFrames);
 580             }
 581             HtmlTree ulAllClasses = HtmlTree.UL(HtmlStyle.navList, getNavLinkClassIndex());
 582             ulAllClasses.addAttr(HtmlAttr.ID, allClassesId);
 583             subDiv.addContent(ulAllClasses);
 584             if (header && configuration.createindex) {
 585                 String searchValueId = "search";
 586                 String reset = "reset";
 587                 HtmlTree inputText = HtmlTree.INPUT("text", searchValueId, searchValueId);
 588                 HtmlTree inputReset = HtmlTree.INPUT(reset, reset, reset);
 589                 Content searchTxt = configuration.getContent("doclet.search");
 590                 HtmlTree liInput = HtmlTree.LI(HtmlTree.LABEL(searchValueId, searchTxt));
 591                 liInput.addContent(inputText);
 592                 liInput.addContent(inputReset);
 593                 HtmlTree ulSearch = HtmlTree.UL(HtmlStyle.navListSearch, liInput);
 594                 subDiv.addContent(ulSearch);
 595             }
 596             subDiv.addContent(getAllClassesLinkScript(allClassesId));
 597             addSummaryDetailLinks(subDiv);
 598             if (header) {
 599                 subDiv.addContent(links.createAnchor(SectionName.SKIP_NAVBAR_TOP));
 600                 fixedNavDiv.addContent(subDiv);
 601                 fixedNavDiv.addContent(HtmlConstants.END_OF_TOP_NAVBAR);
 602                 tree.addContent(fixedNavDiv);
 603                 HtmlTree paddingDiv = HtmlTree.DIV(HtmlStyle.navPadding, Contents.SPACE);
 604                 tree.addContent(paddingDiv);
 605                 Script script = new Script(
 606                         "<!--\n"
 607                         + "$('.navPadding').css('padding-top', $('.fixedNav').css(\"height\"));\n"
 608                         + "//-->\n");
 609                 tree.addContent(script.asContent());
 610             } else {
 611                 subDiv.addContent(links.createAnchor(SectionName.SKIP_NAVBAR_BOTTOM));
 612                 tree.addContent(subDiv);
 613                 tree.addContent(HtmlConstants.END_OF_BOTTOM_NAVBAR);
 614             }
 615             if (configuration.allowTag(HtmlTag.NAV)) {
 616                 htmlTree.addContent(tree);
 617             }
 618         }
 619     }
 620 
 621     /**
 622      * Get the word "NEXT" to indicate that no link is available.  Override
 623      * this method to customize next link.
 624      *
 625      * @return a content tree for the link
 626      */
 627     protected Content getNavLinkNext() {
 628         return getNavLinkNext(null);
 629     }
 630 
 631     /**


 633      * this method to customize prev link.
 634      *
 635      * @return a content tree for the link
 636      */
 637     protected Content getNavLinkPrevious() {
 638         return getNavLinkPrevious(null);
 639     }
 640 
 641     /**
 642      * Do nothing. This is the default method.
 643      */
 644     protected void addSummaryDetailLinks(Content navDiv) {
 645     }
 646 
 647     /**
 648      * Get link to the "overview-summary.html" page.
 649      *
 650      * @return a content tree for the link
 651      */
 652     protected Content getNavLinkContents() {
 653         Content linkContent = Links.createLink(pathToRoot.resolve(DocPaths.overviewSummary(configuration.frames)),
 654                 contents.overviewLabel, "", "");
 655         Content li = HtmlTree.LI(linkContent);
 656         return li;
 657     }
 658 
 659     /**
 660      * Get link to the module summary page for the module passed.
 661      *
 662      * @param mdle Module to which link will be generated
 663      * @return a content tree for the link
 664      */
 665     protected Content getNavLinkModule(ModuleElement mdle) {
 666         Content linkContent = getModuleLink(mdle, contents.moduleLabel);
 667         Content li = HtmlTree.LI(linkContent);
 668         return li;
 669     }
 670 
 671     /**
 672      * Get the word "Module", to indicate that link is not available here.
 673      *


 702 
 703     /**
 704      * Get the word "Use", to indicate that link is not available.
 705      *
 706      * @return a content tree for the link
 707      */
 708     protected Content getNavLinkClassUse() {
 709         Content li = HtmlTree.LI(contents.useLabel);
 710         return li;
 711     }
 712 
 713     /**
 714      * Get link for previous file.
 715      *
 716      * @param prev File name for the prev link
 717      * @return a content tree for the link
 718      */
 719     public Content getNavLinkPrevious(DocPath prev) {
 720         Content li;
 721         if (prev != null) {
 722             li = HtmlTree.LI(Links.createLink(prev, contents.prevLabel, "", ""));
 723         }
 724         else
 725             li = HtmlTree.LI(contents.prevLabel);
 726         return li;
 727     }
 728 
 729     /**
 730      * Get link for next file.  If next is null, just print the label
 731      * without linking it anywhere.
 732      *
 733      * @param next File name for the next link
 734      * @return a content tree for the link
 735      */
 736     public Content getNavLinkNext(DocPath next) {
 737         Content li;
 738         if (next != null) {
 739             li = HtmlTree.LI(Links.createLink(next, contents.nextLabel, "", ""));
 740         }
 741         else
 742             li = HtmlTree.LI(contents.nextLabel);
 743         return li;
 744     }
 745 
 746     /**
 747      * Get "FRAMES" link, to switch to the frame version of the output.
 748      *
 749      * @param link File to be linked, "index.html"
 750      * @return a content tree for the link
 751      */
 752     protected Content getNavShowLists(DocPath link) {
 753         DocLink dl = new DocLink(link, path.getPath(), null);
 754         Content framesContent = Links.createLink(dl, contents.framesLabel, "", "_top");
 755         Content li = HtmlTree.LI(framesContent);
 756         return li;
 757     }
 758 
 759     /**
 760      * Get "FRAMES" link, to switch to the frame version of the output.
 761      *
 762      * @return a content tree for the link
 763      */
 764     protected Content getNavShowLists() {
 765         return getNavShowLists(pathToRoot.resolve(DocPaths.INDEX));
 766     }
 767 
 768     /**
 769      * Get "NO FRAMES" link, to switch to the non-frame version of the output.
 770      *
 771      * @param link File to be linked
 772      * @return a content tree for the link
 773      */
 774     protected Content getNavHideLists(DocPath link) {
 775         Content noFramesContent = Links.createLink(link, contents.noFramesLabel, "", "_top");
 776         Content li = HtmlTree.LI(noFramesContent);
 777         return li;
 778     }
 779 
 780     /**
 781      * Get "Tree" link in the navigation bar. If there is only one package
 782      * specified on the command line, then the "Tree" link will be to the
 783      * only "package-tree.html" file otherwise it will be to the
 784      * "overview-tree.html" file.
 785      *
 786      * @return a content tree for the link
 787      */
 788     protected Content getNavLinkTree() {
 789         List<PackageElement> packages = new ArrayList<>(configuration.getSpecifiedPackageElements());
 790         DocPath docPath = packages.size() == 1 && configuration.getSpecifiedTypeElements().isEmpty()
 791                 ? pathString(packages.get(0), DocPaths.PACKAGE_TREE)
 792                 : pathToRoot.resolve(DocPaths.OVERVIEW_TREE);
 793         return HtmlTree.LI(Links.createLink(docPath, contents.treeLabel, "", ""));
 794     }
 795 
 796     /**
 797      * Get the overview tree link for the main tree.
 798      *
 799      * @param label the label for the link
 800      * @return a content tree for the link
 801      */
 802     protected Content getNavLinkMainTree(String label) {
 803         Content mainTreeContent = Links.createLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE),
 804                 new StringContent(label));
 805         Content li = HtmlTree.LI(mainTreeContent);
 806         return li;
 807     }
 808 
 809     /**
 810      * Get the word "Class", to indicate that class link is not available.
 811      *
 812      * @return a content tree for the link
 813      */
 814     protected Content getNavLinkClass() {
 815         Content li = HtmlTree.LI(contents.classLabel);
 816         return li;
 817     }
 818 
 819     /**
 820      * Get "Deprecated" API link in the navigation bar.
 821      *
 822      * @return a content tree for the link
 823      */
 824     protected Content getNavLinkDeprecated() {
 825         Content linkContent = Links.createLink(pathToRoot.resolve(DocPaths.DEPRECATED_LIST),
 826                 contents.deprecatedLabel, "", "");
 827         Content li = HtmlTree.LI(linkContent);
 828         return li;
 829     }
 830 
 831     /**
 832      * Get link for generated index. If the user has used "-splitindex"
 833      * command line option, then link to file "index-files/index-1.html" is
 834      * generated otherwise link to file "index-all.html" is generated.
 835      *
 836      * @return a content tree for the link
 837      */
 838     protected Content getNavLinkClassIndex() {
 839         Content allClassesContent = Links.createLink(pathToRoot.resolve(
 840                 DocPaths.AllClasses(configuration.frames)),
 841                 contents.allClassesLabel, "", "");
 842         Content li = HtmlTree.LI(allClassesContent);
 843         return li;
 844     }
 845 
 846     /**
 847      * Get link for generated class index.
 848      *
 849      * @return a content tree for the link
 850      */
 851     protected Content getNavLinkIndex() {
 852         Content linkContent = Links.createLink(pathToRoot.resolve(
 853                 (configuration.splitindex
 854                     ? DocPaths.INDEX_FILES.resolve(DocPaths.indexN(1))
 855                     : DocPaths.INDEX_ALL)),
 856             contents.indexLabel, "", "");
 857         Content li = HtmlTree.LI(linkContent);
 858         return li;
 859     }
 860 
 861     /**
 862      * Get help file link. If user has provided a help file, then generate a
 863      * link to the user given file, which is already copied to current or
 864      * destination directory.
 865      *
 866      * @return a content tree for the link
 867      */
 868     protected Content getNavLinkHelp() {
 869         String helpfile = configuration.helpfile;
 870         DocPath helpfilenm;
 871         if (helpfile.isEmpty()) {
 872             helpfilenm = DocPaths.HELP_DOC;
 873         } else {
 874             DocFile file = DocFile.createFileForInput(configuration, helpfile);
 875             helpfilenm = DocPath.create(file.getName());
 876         }
 877         Content linkContent = Links.createLink(pathToRoot.resolve(helpfilenm),
 878                 contents.helpLabel, "", "");
 879         Content li = HtmlTree.LI(linkContent);
 880         return li;
 881     }
 882 
 883     /**
 884      * Add gap between navigation bar elements.
 885      *
 886      * @param liNav the content tree to which the gap will be added
 887      */
 888     protected void addNavGap(Content liNav) {
 889         liNav.addContent(Contents.SPACE);
 890         liNav.addContent("|");
 891         liNav.addContent(Contents.SPACE);
 892     }
 893 
 894     /**
 895      * Get table caption.
 896      *
 897      * @param title the content for the caption
 898      * @return a content tree for the caption
 899      */
 900     public Content getTableCaption(Content title) {
 901         Content captionSpan = HtmlTree.SPAN(title);
 902         Content space = Contents.SPACE;
 903         Content tabSpan = HtmlTree.SPAN(HtmlStyle.tabEnd, space);
 904         Content caption = HtmlTree.CAPTION(captionSpan);
 905         caption.addContent(tabSpan);
 906         return caption;
 907     }
 908 
 909     /**













































 910      * Returns a packagename content.
 911      *
 912      * @param packageElement the package to check
 913      * @return package name content
 914      */
 915     public Content getPackageName(PackageElement packageElement) {
 916         return packageElement == null || packageElement.isUnnamed()
 917                 ? contents.defaultPackageLabel
 918                 : getPackageLabel(packageElement.getQualifiedName());
 919     }
 920 
 921     /**
 922      * Returns a package name label.
 923      *
 924      * @param packageName the package name
 925      * @return the package name content
 926      */
 927     public Content getPackageLabel(CharSequence packageName) {
 928         return new StringContent(packageName);
 929     }


 981     }
 982 
 983     /**
 984      * Return the link to the given package.
 985      *
 986      * @param packageElement the package to link to.
 987      * @param label the label for the link.
 988      * @return a content tree for the package link.
 989      */
 990     public Content getPackageLink(PackageElement packageElement, Content label) {
 991         boolean included = packageElement != null && utils.isIncluded(packageElement);
 992         if (!included) {
 993             for (PackageElement p : configuration.packages) {
 994                 if (p.equals(packageElement)) {
 995                     included = true;
 996                     break;
 997                 }
 998             }
 999         }
1000         if (included || packageElement == null) {
1001             return Links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
1002                     label);
1003         } else {
1004             DocLink crossPkgLink = getCrossPackageLink(utils.getPackageName(packageElement));
1005             if (crossPkgLink != null) {
1006                 return Links.createLink(crossPkgLink, label);
1007             } else {
1008                 return label;
1009             }
1010         }
1011     }
1012 
1013     /**
1014      * Get Module link.
1015      *
1016      * @param mdle the module being documented
1017      * @param label tag for the link
1018      * @return a content for the module link
1019      */
1020     public Content getModuleLink(ModuleElement mdle, Content label) {
1021         boolean included = utils.isIncluded(mdle);
1022         return (included)
1023                 ? Links.createLink(pathToRoot.resolve(DocPaths.moduleSummary(mdle)), label, "", "")
1024                 : label;
1025     }
1026 
1027     public Content interfaceName(TypeElement typeElement, boolean qual) {
1028         Content name = new StringContent((qual)
1029                 ? typeElement.getQualifiedName()
1030                 : utils.getSimpleName(typeElement));
1031         return (utils.isInterface(typeElement)) ?  HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name;
1032     }
1033 
1034     /**
1035      * Add the link to the content tree.
1036      *
1037      * @param typeElement program element typeElement for which the link will be added
1038      * @param label label for the link
1039      * @param htmltree the content tree to which the link will be added
1040      */
1041     public void addSrcLink(Element typeElement, Content label, Content htmltree) {
1042         if (typeElement == null) {
1043             return;
1044         }
1045         TypeElement te = utils.getEnclosingTypeElement(typeElement);
1046         if (te == null) {
1047             // must be a typeElement since in has no containing class.
1048             te = (TypeElement) typeElement;
1049         }
1050         DocPath href = pathToRoot
1051                 .resolve(DocPaths.SOURCE_OUTPUT)
1052                 .resolve(DocPath.forClass(utils, te));
1053         Content linkContent = Links.createLink(href
1054                 .fragment(SourceToHTMLConverter.getAnchorName(utils, typeElement)), label, "", "");
1055         htmltree.addContent(linkContent);
1056     }
1057 
1058     /**
1059      * Return the link to the given class.
1060      *
1061      * @param linkInfo the information about the link.
1062      *
1063      * @return the link for the given class.
1064      */
1065     public Content getLink(LinkInfoImpl linkInfo) {
1066         LinkFactoryImpl factory = new LinkFactoryImpl(this);
1067         return factory.getLink(linkInfo);
1068     }
1069 
1070     /**
1071      * Return the type parameters for the given class.
1072      *
1073      * @param linkInfo the information about the link.


1098         String className = "";
1099         String packageName = qualifiedClassName == null ? "" : qualifiedClassName;
1100         int periodIndex;
1101         while ((periodIndex = packageName.lastIndexOf('.')) != -1) {
1102             className = packageName.substring(periodIndex + 1, packageName.length()) +
1103                 (className.length() > 0 ? "." + className : "");
1104             Content defaultLabel = new StringContent(className);
1105             if (code)
1106                 defaultLabel = HtmlTree.CODE(defaultLabel);
1107             packageName = packageName.substring(0, periodIndex);
1108             if (getCrossPackageLink(packageName) != null) {
1109                 /*
1110                 The package exists in external documentation, so link to the external
1111                 class (assuming that it exists).  This is definitely a limitation of
1112                 the -link option.  There are ways to determine if an external package
1113                 exists, but no way to determine if the external class exists.  We just
1114                 have to assume that it does.
1115                 */
1116                 DocLink link = configuration.extern.getExternalLink(packageName, pathToRoot,
1117                                 className + ".html", refMemName);
1118                 return Links.createLink(link,
1119                     (label == null) || label.isEmpty() ? defaultLabel : label,
1120                     strong, style,
1121                     configuration.getText("doclet.Href_Class_Or_Interface_Title", packageName),
1122                     "");
1123             }
1124         }
1125         return null;
1126     }
1127 
1128     public boolean isClassLinkable(TypeElement typeElement) {
1129         if (utils.isIncluded(typeElement)) {
1130             return configuration.isGeneratedDoc(typeElement);
1131         }
1132         return configuration.extern.isExternal(typeElement);
1133     }
1134 
1135     public DocLink getCrossPackageLink(String pkgName) {
1136         return configuration.extern.getExternalLink(pkgName, pathToRoot,
1137             DocPaths.PACKAGE_SUMMARY.getPath());
1138     }


1282             CharSequence label, boolean strong, boolean isProperty) {
1283         return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty);
1284     }
1285 
1286     CharSequence check(CharSequence s) {
1287         Matcher m = IMPROPER_HTML_CHARS.matcher(s);
1288         if (m.matches()) {
1289             throw new IllegalArgumentException(s.toString());
1290         }
1291         return s;
1292     }
1293 
1294     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
1295             Content label, boolean strong, boolean isProperty) {
1296         if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) {
1297             return label;
1298         } else if (utils.isExecutableElement(element)) {
1299             ExecutableElement ee = (ExecutableElement)element;
1300             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1301                 .label(label)
1302                 .where(links.getName(getAnchor(ee, isProperty)))
1303                 .strong(strong));
1304         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
1305             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1306                 .label(label)
1307                 .where(links.getName(element.getSimpleName().toString()))
1308                 .strong(strong));
1309         } else {
1310             return label;
1311         }
1312     }
1313 
1314     /**
1315      * Return the link for the given member.
1316      *
1317      * @param context the id of the context where the link will be added
1318      * @param typeElement the typeElement that we should link to.  This is not
1319                  necessarily equal to element.containingClass().  We may be
1320                  inheriting comments
1321      * @param element the member being linked to
1322      * @param label the label for the link
1323      * @return the link for the given member
1324      */
1325     public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
1326             Content label) {
1327         if (! (utils.isIncluded(element) || utils.isLinkable(typeElement))) {
1328             return label;
1329         } else if (utils.isExecutableElement(element)) {
1330             ExecutableElement emd = (ExecutableElement) element;
1331             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1332                 .label(label)
1333                 .where(links.getName(getAnchor(emd))));
1334         } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
1335             return getLink(new LinkInfoImpl(configuration, context, typeElement)
1336                 .label(label).where(links.getName(element.getSimpleName().toString())));
1337         } else {
1338             return label;
1339         }
1340     }
1341 
1342     public String getAnchor(ExecutableElement executableElement) {
1343         return getAnchor(executableElement, false);
1344     }
1345 
1346     public String getAnchor(ExecutableElement executableElement, boolean isProperty) {
1347         if (isProperty) {
1348             return executableElement.getSimpleName().toString();
1349         }
1350         String member = anchorName(executableElement);
1351         String erasedSignature = utils.makeSignature(executableElement, true, true);
1352         return member + erasedSignature;
1353     }
1354 
1355     public String anchorName(Element member) {
1356         if (member.getKind() == ElementKind.CONSTRUCTOR


1387         String refMemName =    ch.getReferencedMemberName(see);
1388 
1389         if (refMemName == null && refMem != null) {
1390             refMemName = refMem.toString();
1391         }
1392         if (refClass == null) {
1393             //@see is not referencing an included class
1394             PackageElement refPackage = ch.getReferencedPackage(configuration, see);
1395             if (refPackage != null && utils.isIncluded(refPackage)) {
1396                 //@see is referencing an included package
1397                 if (label.isEmpty())
1398                     label = plainOrCode(isLinkPlain,
1399                             new StringContent(refPackage.getQualifiedName()));
1400                 return getPackageLink(refPackage, label);
1401             } else {
1402                 // @see is not referencing an included class or package.  Check for cross links.
1403                 Content classCrossLink;
1404                 DocLink packageCrossLink = getCrossPackageLink(refClassName);
1405                 if (packageCrossLink != null) {
1406                     // Package cross link found
1407                     return Links.createLink(packageCrossLink,
1408                         (label.isEmpty() ? text : label));
1409                 } else if ((classCrossLink = getCrossClassLink(refClassName,
1410                         refMemName, label, false, "", !isLinkPlain)) != null) {
1411                     // Class cross link found (possibly to a member in the class)
1412                     return classCrossLink;
1413                 } else {
1414                     // No cross link found so print warning
1415                     messages.warning(ch.getDocTreePath(see),
1416                             "doclet.see.class_or_package_not_found",
1417                             "@" + tagName,
1418                             seetext);
1419                     return (label.isEmpty() ? text: label);
1420                 }
1421             }
1422         } else if (refMemName == null) {
1423             // Must be a class reference since refClass is not null and refMemName is null.
1424             if (label.isEmpty()) {
1425                 /*
1426                  * it seems to me this is the right thing to do, but it causes comparator failures.
1427                  */


< prev index next >