1 /*
   2  * Copyright (c) 1998, 2017, 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  */
  25 
  26 package jdk.javadoc.internal.doclets.formats.html;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Collections;
  30 import java.util.HashMap;
  31 import java.util.List;
  32 import java.util.Map;
  33 import java.util.Set;
  34 import java.util.SortedSet;
  35 import java.util.TreeSet;
  36 
  37 import javax.lang.model.element.Element;
  38 import javax.lang.model.element.PackageElement;
  39 import javax.lang.model.element.TypeElement;
  40 import javax.tools.Diagnostic;
  41 
  42 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  43 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  44 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  45 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  46 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  47 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  48 import jdk.javadoc.internal.doclets.toolkit.Content;
  49 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
  50 import jdk.javadoc.internal.doclets.toolkit.util.ClassUseMapper;
  51 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  52 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  53 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  54 
  55 
  56 /**
  57  * Generate class usage information.
  58  *
  59  *  <p><b>This is NOT part of any supported API.
  60  *  If you write code that depends on this, you do so at your own risk.
  61  *  This code and its internal interfaces are subject to change or
  62  *  deletion without notice.</b>
  63  *
  64  * @author Robert G. Field
  65  * @author Bhavesh Patel (Modified)
  66  */
  67 public class ClassUseWriter extends SubWriterHolderWriter {
  68 
  69     final TypeElement typeElement;
  70     Set<PackageElement> pkgToPackageAnnotations = null;
  71     final Map<PackageElement, List<Element>> pkgToClassTypeParameter;
  72     final Map<PackageElement, List<Element>> pkgToClassAnnotations;
  73     final Map<PackageElement, List<Element>> pkgToMethodTypeParameter;
  74     final Map<PackageElement, List<Element>> pkgToMethodArgTypeParameter;
  75     final Map<PackageElement, List<Element>> pkgToMethodReturnTypeParameter;
  76     final Map<PackageElement, List<Element>> pkgToMethodAnnotations;
  77     final Map<PackageElement, List<Element>> pkgToMethodParameterAnnotations;
  78     final Map<PackageElement, List<Element>> pkgToFieldTypeParameter;
  79     final Map<PackageElement, List<Element>> pkgToFieldAnnotations;
  80     final Map<PackageElement, List<Element>> pkgToSubclass;
  81     final Map<PackageElement, List<Element>> pkgToSubinterface;
  82     final Map<PackageElement, List<Element>> pkgToImplementingClass;
  83     final Map<PackageElement, List<Element>> pkgToField;
  84     final Map<PackageElement, List<Element>> pkgToMethodReturn;
  85     final Map<PackageElement, List<Element>> pkgToMethodArgs;
  86     final Map<PackageElement, List<Element>> pkgToMethodThrows;
  87     final Map<PackageElement, List<Element>> pkgToConstructorAnnotations;
  88     final Map<PackageElement, List<Element>> pkgToConstructorParameterAnnotations;
  89     final Map<PackageElement, List<Element>> pkgToConstructorArgs;
  90     final Map<PackageElement, List<Element>> pkgToConstructorArgTypeParameter;
  91     final Map<PackageElement, List<Element>> pkgToConstructorThrows;
  92     final SortedSet<PackageElement> pkgSet;
  93     final MethodWriterImpl methodSubWriter;
  94     final ConstructorWriterImpl constrSubWriter;
  95     final FieldWriterImpl fieldSubWriter;
  96     final NestedClassWriterImpl classSubWriter;
  97     // Summary for various use tables.
  98     final String classUseTableSummary;
  99     final String subclassUseTableSummary;
 100     final String subinterfaceUseTableSummary;
 101     final String fieldUseTableSummary;
 102     final String methodUseTableSummary;
 103     final String constructorUseTableSummary;
 104 
 105     /**
 106      * The HTML tree for main tag.
 107      */
 108     protected HtmlTree mainTree = HtmlTree.MAIN();
 109 
 110     /**
 111      * Constructor.
 112      *
 113      * @param filename the file to be generated.
 114      */
 115     public ClassUseWriter(HtmlConfiguration configuration,
 116                           ClassUseMapper mapper, DocPath filename,
 117                           TypeElement typeElement) {
 118         super(configuration, filename);
 119         this.typeElement = typeElement;
 120         if (mapper.classToPackageAnnotations.containsKey(typeElement)) {
 121             pkgToPackageAnnotations = new TreeSet<>(utils.makeClassUseComparator());
 122             pkgToPackageAnnotations.addAll(mapper.classToPackageAnnotations.get(typeElement));
 123         }
 124         configuration.currentTypeElement = typeElement;
 125         this.pkgSet = new TreeSet<>(utils.makePackageComparator());
 126         this.pkgToClassTypeParameter = pkgDivide(mapper.classToClassTypeParam);
 127         this.pkgToClassAnnotations = pkgDivide(mapper.classToClassAnnotations);
 128         this.pkgToMethodTypeParameter = pkgDivide(mapper.classToMethodTypeParam);
 129         this.pkgToMethodArgTypeParameter = pkgDivide(mapper.classToMethodArgTypeParam);
 130         this.pkgToFieldTypeParameter = pkgDivide(mapper.classToFieldTypeParam);
 131         this.pkgToFieldAnnotations = pkgDivide(mapper.annotationToField);
 132         this.pkgToMethodReturnTypeParameter = pkgDivide(mapper.classToMethodReturnTypeParam);
 133         this.pkgToMethodAnnotations = pkgDivide(mapper.classToMethodAnnotations);
 134         this.pkgToMethodParameterAnnotations = pkgDivide(mapper.classToMethodParamAnnotation);
 135         this.pkgToSubclass = pkgDivide(mapper.classToSubclass);
 136         this.pkgToSubinterface = pkgDivide(mapper.classToSubinterface);
 137         this.pkgToImplementingClass = pkgDivide(mapper.classToImplementingClass);
 138         this.pkgToField = pkgDivide(mapper.classToField);
 139         this.pkgToMethodReturn = pkgDivide(mapper.classToMethodReturn);
 140         this.pkgToMethodArgs = pkgDivide(mapper.classToMethodArgs);
 141         this.pkgToMethodThrows = pkgDivide(mapper.classToMethodThrows);
 142         this.pkgToConstructorAnnotations = pkgDivide(mapper.classToConstructorAnnotations);
 143         this.pkgToConstructorParameterAnnotations = pkgDivide(mapper.classToConstructorParamAnnotation);
 144         this.pkgToConstructorArgs = pkgDivide(mapper.classToConstructorArgs);
 145         this.pkgToConstructorArgTypeParameter = pkgDivide(mapper.classToConstructorArgTypeParam);
 146         this.pkgToConstructorThrows = pkgDivide(mapper.classToConstructorThrows);
 147         //tmp test
 148         if (pkgSet.size() > 0 &&
 149             mapper.classToPackage.containsKey(this.typeElement) &&
 150             !pkgSet.equals(mapper.classToPackage.get(this.typeElement))) {
 151             configuration.reporter.print(Diagnostic.Kind.WARNING,
 152                     "Internal error: package sets don't match: "
 153                     + pkgSet + " with: " + mapper.classToPackage.get(this.typeElement));
 154         }
 155         methodSubWriter = new MethodWriterImpl(this);
 156         constrSubWriter = new ConstructorWriterImpl(this);
 157         fieldSubWriter = new FieldWriterImpl(this);
 158         classSubWriter = new NestedClassWriterImpl(this);
 159         classUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 160                 configuration.getText("doclet.classes"));
 161         subclassUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 162                 configuration.getText("doclet.subclasses"));
 163         subinterfaceUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 164                 configuration.getText("doclet.subinterfaces"));
 165         fieldUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 166                 configuration.getText("doclet.fields"));
 167         methodUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 168                 configuration.getText("doclet.methods"));
 169         constructorUseTableSummary = configuration.getText("doclet.Use_Table_Summary",
 170                 configuration.getText("doclet.constructors"));
 171     }
 172 
 173     /**
 174      * Write out class use pages.
 175      *
 176      * @param configuration the configuration for this doclet
 177      * @param classtree the class tree hierarchy
 178      * @throws DocFileIOException if there is an error while generating the documentation
 179      */
 180     public static void generate(HtmlConfiguration configuration, ClassTree classtree) throws DocFileIOException  {
 181         ClassUseMapper mapper = new ClassUseMapper(configuration, classtree);
 182         for (TypeElement aClass : configuration.getIncludedTypeElements()) {
 183             // If -nodeprecated option is set and the containing package is marked
 184             // as deprecated, do not generate the class-use page. We will still generate
 185             // the class-use page if the class is marked as deprecated but the containing
 186             // package is not since it could still be linked from that package-use page.
 187             if (!(configuration.nodeprecated &&
 188                   configuration.utils.isDeprecated(configuration.utils.containingPackage(aClass))))
 189                 ClassUseWriter.generate(configuration, mapper, aClass);
 190         }
 191         for (PackageElement pkg : configuration.packages) {
 192             // If -nodeprecated option is set and the package is marked
 193             // as deprecated, do not generate the package-use page.
 194             if (!(configuration.nodeprecated && configuration.utils.isDeprecated(pkg)))
 195                 PackageUseWriter.generate(configuration, mapper, pkg);
 196         }
 197     }
 198 
 199     private Map<PackageElement, List<Element>> pkgDivide(Map<TypeElement, ? extends List<? extends Element>> classMap) {
 200         Map<PackageElement, List<Element>> map = new HashMap<>();
 201         List<? extends Element> elements = (List<? extends Element>) classMap.get(typeElement);
 202         if (elements != null) {
 203             Collections.sort(elements, utils.makeClassUseComparator());
 204             for (Element e : elements) {
 205                 PackageElement pkg = utils.containingPackage(e);
 206                 pkgSet.add(pkg);
 207                 List<Element> inPkg = map.get(pkg);
 208                 if (inPkg == null) {
 209                     inPkg = new ArrayList<>();
 210                     map.put(pkg, inPkg);
 211                 }
 212                 inPkg.add(e);
 213             }
 214         }
 215         return map;
 216     }
 217 
 218     /**
 219      * Generate a class page.
 220      *
 221      * @throws DocFileIOException if there is a problem while generating the documentation
 222      */
 223     public static void generate(HtmlConfiguration configuration, ClassUseMapper mapper,
 224                                 TypeElement typeElement) throws DocFileIOException {
 225         ClassUseWriter clsgen;
 226         DocPath path = DocPath.forPackage(configuration.utils, typeElement)
 227                               .resolve(DocPaths.CLASS_USE)
 228                               .resolve(DocPath.forName(configuration.utils, typeElement));
 229         clsgen = new ClassUseWriter(configuration, mapper, path, typeElement);
 230         clsgen.generateClassUseFile();
 231     }
 232 
 233     /**
 234      * Generate the class use elements.
 235      *
 236      * @throws DocFileIOException if there is a problem while generating the documentation
 237      */
 238     protected void generateClassUseFile() throws DocFileIOException {
 239         HtmlTree body = getClassUseHeader();
 240         HtmlTree div = new HtmlTree(HtmlTag.DIV);
 241         div.addStyle(HtmlStyle.classUseContainer);
 242         if (pkgSet.size() > 0) {
 243             addClassUse(div);
 244         } else {
 245             div.addContent(contents.getContent("doclet.ClassUse_No.usage.of.0",
 246                     utils.getFullyQualifiedName(typeElement)));
 247         }
 248         if (configuration.allowTag(HtmlTag.MAIN)) {
 249             mainTree.addContent(div);
 250             body.addContent(mainTree);
 251         } else {
 252             body.addContent(div);
 253         }
 254         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.FOOTER))
 255                 ? HtmlTree.FOOTER()
 256                 : body;
 257         addNavLinks(false, htmlTree);
 258         addBottom(htmlTree);
 259         if (configuration.allowTag(HtmlTag.FOOTER)) {
 260             body.addContent(htmlTree);
 261         }
 262         printHtmlDocument(null, true, body);
 263     }
 264 
 265     /**
 266      * Add the class use documentation.
 267      *
 268      * @param contentTree the content tree to which the class use information will be added
 269      */
 270     protected void addClassUse(Content contentTree) {
 271         HtmlTree ul = new HtmlTree(HtmlTag.UL);
 272         ul.addStyle(HtmlStyle.blockList);
 273         if (configuration.packages.size() > 1) {
 274             addPackageList(ul);
 275             addPackageAnnotationList(ul);
 276         }
 277         addClassList(ul);
 278         contentTree.addContent(ul);
 279     }
 280 
 281     /**
 282      * Add the packages elements that use the given class.
 283      *
 284      * @param contentTree the content tree to which the packages elements will be added
 285      */
 286     protected void addPackageList(Content contentTree) {
 287         Content caption = getTableCaption(configuration.getContent(
 288                 "doclet.ClassUse_Packages.that.use.0",
 289                 getLink(new LinkInfoImpl(configuration,
 290                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
 291         Content table = (configuration.isOutputHtml5())
 292                 ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
 293                 : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption);
 294         table.addContent(getSummaryTableHeader(packageTableHeader, "col"));
 295         Content tbody = new HtmlTree(HtmlTag.TBODY);
 296         boolean altColor = true;
 297         for (PackageElement pkg : pkgSet) {
 298             HtmlTree tr = new HtmlTree(HtmlTag.TR);
 299             tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
 300             altColor = !altColor;
 301             addPackageUse(pkg, tr);
 302             tbody.addContent(tr);
 303         }
 304         table.addContent(tbody);
 305         Content li = HtmlTree.LI(HtmlStyle.blockList, table);
 306         contentTree.addContent(li);
 307     }
 308 
 309     /**
 310      * Add the package annotation elements.
 311      *
 312      * @param contentTree the content tree to which the package annotation elements will be added
 313      */
 314     protected void addPackageAnnotationList(Content contentTree) {
 315         if (!utils.isAnnotationType(typeElement) ||
 316                 pkgToPackageAnnotations == null ||
 317                 pkgToPackageAnnotations.isEmpty()) {
 318             return;
 319         }
 320         Content caption = getTableCaption(configuration.getContent(
 321                 "doclet.ClassUse_PackageAnnotation",
 322                 getLink(new LinkInfoImpl(configuration,
 323                         LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement))));
 324         Content table = (configuration.isOutputHtml5())
 325                 ? HtmlTree.TABLE(HtmlStyle.useSummary, caption)
 326                 : HtmlTree.TABLE(HtmlStyle.useSummary, useTableSummary, caption);
 327         table.addContent(getSummaryTableHeader(packageTableHeader, "col"));
 328         Content tbody = new HtmlTree(HtmlTag.TBODY);
 329         boolean altColor = true;
 330         for (PackageElement pkg : pkgToPackageAnnotations) {
 331             HtmlTree tr = new HtmlTree(HtmlTag.TR);
 332             tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
 333             altColor = !altColor;
 334             Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst, getPackageLink(pkg));
 335             tr.addContent(thFirst);
 336             HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
 337             tdLast.addStyle(HtmlStyle.colLast);
 338             addSummaryComment(pkg, tdLast);
 339             tr.addContent(tdLast);
 340             tbody.addContent(tr);
 341         }
 342         table.addContent(tbody);
 343         Content li = HtmlTree.LI(HtmlStyle.blockList, table);
 344         contentTree.addContent(li);
 345     }
 346 
 347     /**
 348      * Add the class elements that use the given class.
 349      *
 350      * @param contentTree the content tree to which the class elements will be added
 351      */
 352     protected void addClassList(Content contentTree) {
 353         HtmlTree ul = new HtmlTree(HtmlTag.UL);
 354         ul.addStyle(HtmlStyle.blockList);
 355         for (PackageElement pkg : pkgSet) {
 356             Content markerAnchor = getMarkerAnchor(getPackageAnchorName(pkg));
 357             HtmlTree htmlTree = (configuration.allowTag(HtmlTag.SECTION))
 358                     ? HtmlTree.SECTION(markerAnchor)
 359                     : HtmlTree.LI(HtmlStyle.blockList, markerAnchor);
 360             Content link = contents.getContent("doclet.ClassUse_Uses.of.0.in.1",
 361                     getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER,
 362                             typeElement)),
 363                     getPackageLink(pkg, utils.getPackageName(pkg)));
 364             Content heading = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, link);
 365             htmlTree.addContent(heading);
 366             addClassUse(pkg, htmlTree);
 367             if (configuration.allowTag(HtmlTag.SECTION)) {
 368                 ul.addContent(HtmlTree.LI(HtmlStyle.blockList, htmlTree));
 369             } else {
 370                 ul.addContent(htmlTree);
 371             }
 372         }
 373         Content li = HtmlTree.LI(HtmlStyle.blockList, ul);
 374         contentTree.addContent(li);
 375     }
 376 
 377     /**
 378      * Add the package use information.
 379      *
 380      * @param pkg the package that uses the given class
 381      * @param contentTree the content tree to which the package use information will be added
 382      */
 383     protected void addPackageUse(PackageElement pkg, Content contentTree) {
 384         Content thFirst = HtmlTree.TH_ROW_SCOPE(HtmlStyle.colFirst,
 385                 getHyperLink(getPackageAnchorName(pkg), new StringContent(utils.getPackageName(pkg))));
 386         contentTree.addContent(thFirst);
 387         HtmlTree tdLast = new HtmlTree(HtmlTag.TD);
 388         tdLast.addStyle(HtmlStyle.colLast);
 389         addSummaryComment(pkg, tdLast);
 390         contentTree.addContent(tdLast);
 391     }
 392 
 393     /**
 394      * Add the class use information.
 395      *
 396      * @param pkg the package that uses the given class
 397      * @param contentTree the content tree to which the class use information will be added
 398      */
 399     protected void addClassUse(PackageElement pkg, Content contentTree) {
 400         Content classLink = getLink(new LinkInfoImpl(configuration,
 401             LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement));
 402         Content pkgLink = getPackageLink(pkg, utils.getPackageName(pkg));
 403         classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg),
 404                 configuration.getContent("doclet.ClassUse_Annotation", classLink,
 405                 pkgLink), classUseTableSummary, contentTree);
 406         classSubWriter.addUseInfo(pkgToClassTypeParameter.get(pkg),
 407                 configuration.getContent("doclet.ClassUse_TypeParameter", classLink,
 408                 pkgLink), classUseTableSummary, contentTree);
 409         classSubWriter.addUseInfo(pkgToSubclass.get(pkg),
 410                 configuration.getContent("doclet.ClassUse_Subclass", classLink,
 411                 pkgLink), subclassUseTableSummary, contentTree);
 412         classSubWriter.addUseInfo(pkgToSubinterface.get(pkg),
 413                 configuration.getContent("doclet.ClassUse_Subinterface", classLink,
 414                 pkgLink), subinterfaceUseTableSummary, contentTree);
 415         classSubWriter.addUseInfo(pkgToImplementingClass.get(pkg),
 416                 configuration.getContent("doclet.ClassUse_ImplementingClass", classLink,
 417                 pkgLink), classUseTableSummary, contentTree);
 418         fieldSubWriter.addUseInfo(pkgToField.get(pkg),
 419                 configuration.getContent("doclet.ClassUse_Field", classLink,
 420                 pkgLink), fieldUseTableSummary, contentTree);
 421         fieldSubWriter.addUseInfo(pkgToFieldAnnotations.get(pkg),
 422                 configuration.getContent("doclet.ClassUse_FieldAnnotations", classLink,
 423                 pkgLink), fieldUseTableSummary, contentTree);
 424         fieldSubWriter.addUseInfo(pkgToFieldTypeParameter.get(pkg),
 425                 configuration.getContent("doclet.ClassUse_FieldTypeParameter", classLink,
 426                 pkgLink), fieldUseTableSummary, contentTree);
 427         methodSubWriter.addUseInfo(pkgToMethodAnnotations.get(pkg),
 428                 configuration.getContent("doclet.ClassUse_MethodAnnotations", classLink,
 429                 pkgLink), methodUseTableSummary, contentTree);
 430         methodSubWriter.addUseInfo(pkgToMethodParameterAnnotations.get(pkg),
 431                 configuration.getContent("doclet.ClassUse_MethodParameterAnnotations", classLink,
 432                 pkgLink), methodUseTableSummary, contentTree);
 433         methodSubWriter.addUseInfo(pkgToMethodTypeParameter.get(pkg),
 434                 configuration.getContent("doclet.ClassUse_MethodTypeParameter", classLink,
 435                 pkgLink), methodUseTableSummary, contentTree);
 436         methodSubWriter.addUseInfo(pkgToMethodReturn.get(pkg),
 437                 configuration.getContent("doclet.ClassUse_MethodReturn", classLink,
 438                 pkgLink), methodUseTableSummary, contentTree);
 439         methodSubWriter.addUseInfo(pkgToMethodReturnTypeParameter.get(pkg),
 440                 configuration.getContent("doclet.ClassUse_MethodReturnTypeParameter", classLink,
 441                 pkgLink), methodUseTableSummary, contentTree);
 442         methodSubWriter.addUseInfo(pkgToMethodArgs.get(pkg),
 443                 configuration.getContent("doclet.ClassUse_MethodArgs", classLink,
 444                 pkgLink), methodUseTableSummary, contentTree);
 445         methodSubWriter.addUseInfo(pkgToMethodArgTypeParameter.get(pkg),
 446                 configuration.getContent("doclet.ClassUse_MethodArgsTypeParameters", classLink,
 447                 pkgLink), methodUseTableSummary, contentTree);
 448         methodSubWriter.addUseInfo(pkgToMethodThrows.get(pkg),
 449                 configuration.getContent("doclet.ClassUse_MethodThrows", classLink,
 450                 pkgLink), methodUseTableSummary, contentTree);
 451         constrSubWriter.addUseInfo(pkgToConstructorAnnotations.get(pkg),
 452                 configuration.getContent("doclet.ClassUse_ConstructorAnnotations", classLink,
 453                 pkgLink), constructorUseTableSummary, contentTree);
 454         constrSubWriter.addUseInfo(pkgToConstructorParameterAnnotations.get(pkg),
 455                 configuration.getContent("doclet.ClassUse_ConstructorParameterAnnotations", classLink,
 456                 pkgLink), constructorUseTableSummary, contentTree);
 457         constrSubWriter.addUseInfo(pkgToConstructorArgs.get(pkg),
 458                 configuration.getContent("doclet.ClassUse_ConstructorArgs", classLink,
 459                 pkgLink), constructorUseTableSummary, contentTree);
 460         constrSubWriter.addUseInfo(pkgToConstructorArgTypeParameter.get(pkg),
 461                 configuration.getContent("doclet.ClassUse_ConstructorArgsTypeParameters", classLink,
 462                 pkgLink), constructorUseTableSummary, contentTree);
 463         constrSubWriter.addUseInfo(pkgToConstructorThrows.get(pkg),
 464                 configuration.getContent("doclet.ClassUse_ConstructorThrows", classLink,
 465                 pkgLink), constructorUseTableSummary, contentTree);
 466     }
 467 
 468     /**
 469      * Get the header for the class use Listing.
 470      *
 471      * @return a content tree representing the class use header
 472      */
 473     protected HtmlTree getClassUseHeader() {
 474         String cltype = configuration.getText(utils.isInterface(typeElement)
 475                 ? "doclet.Interface"
 476                 : "doclet.Class");
 477         String clname = utils.getFullyQualifiedName(typeElement);
 478         String title = configuration.getText("doclet.Window_ClassUse_Header",
 479                 cltype, clname);
 480         HtmlTree bodyTree = getBody(true, getWindowTitle(title));
 481         HtmlTree htmlTree = (configuration.allowTag(HtmlTag.HEADER))
 482                 ? HtmlTree.HEADER()
 483                 : bodyTree;
 484         addTop(htmlTree);
 485         addNavLinks(true, htmlTree);
 486         if (configuration.allowTag(HtmlTag.HEADER)) {
 487             bodyTree.addContent(htmlTree);
 488         }
 489         ContentBuilder headContent = new ContentBuilder();
 490         headContent.addContent(contents.getContent("doclet.ClassUse_Title", cltype));
 491         headContent.addContent(new HtmlTree(HtmlTag.BR));
 492         headContent.addContent(clname);
 493         Content heading = HtmlTree.HEADING(HtmlConstants.CLASS_PAGE_HEADING,
 494                 true, HtmlStyle.title, headContent);
 495         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
 496         if (configuration.allowTag(HtmlTag.MAIN)) {
 497             mainTree.addContent(div);
 498         } else {
 499             bodyTree.addContent(div);
 500         }
 501         return bodyTree;
 502     }
 503 
 504     /**
 505      * Get the module link.
 506      *
 507      * @return a content tree for the module link
 508      */
 509     @Override
 510     protected Content getNavLinkModule() {
 511         Content linkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
 512                 contents.moduleLabel);
 513         Content li = HtmlTree.LI(linkContent);
 514         return li;
 515     }
 516 
 517     /**
 518      * Get this package link.
 519      *
 520      * @return a content tree for the package link
 521      */
 522     protected Content getNavLinkPackage() {
 523         Content linkContent =
 524                 getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_SUMMARY), contents.packageLabel);
 525         Content li = HtmlTree.LI(linkContent);
 526         return li;
 527     }
 528 
 529     /**
 530      * Get class page link.
 531      *
 532      * @return a content tree for the class page link
 533      */
 534     protected Content getNavLinkClass() {
 535         Content linkContent = getLink(new LinkInfoImpl(
 536                 configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)
 537                 .label(configuration.getText("doclet.Class")));
 538         Content li = HtmlTree.LI(linkContent);
 539         return li;
 540     }
 541 
 542     /**
 543      * Get the use link.
 544      *
 545      * @return a content tree for the use link
 546      */
 547     protected Content getNavLinkClassUse() {
 548         Content li = HtmlTree.LI(HtmlStyle.navBarCell1Rev, contents.useLabel);
 549         return li;
 550     }
 551 
 552     /**
 553      * Get the tree link.
 554      *
 555      * @return a content tree for the tree link
 556      */
 557     protected Content getNavLinkTree() {
 558         Content linkContent = utils.isEnclosingPackageIncluded(typeElement)
 559                 ? getHyperLink(DocPath.parent.resolve(DocPaths.PACKAGE_TREE), contents.treeLabel)
 560                 : getHyperLink(pathToRoot.resolve(DocPaths.OVERVIEW_TREE), contents.treeLabel);
 561         Content li = HtmlTree.LI(linkContent);
 562         return li;
 563     }
 564 }