1 /*
   2  * Copyright (c) 1997, 2019, 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.SortedSet;
  29 
  30 import javax.lang.model.element.PackageElement;
  31 
  32 import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
  33 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  34 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  35 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  36 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  37 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
  38 import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
  39 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  40 import jdk.javadoc.internal.doclets.toolkit.Content;
  41 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
  42 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
  43 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  44 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  45 
  46 /**
  47  * Generate Class Hierarchy page for all the Classes in this run.  Use
  48  * ClassTree for building the Tree. The name of
  49  * the generated file is "overview-tree.html" and it is generated in the
  50  * current or the destination directory.
  51  *
  52  *  <p><b>This is NOT part of any supported API.
  53  *  If you write code that depends on this, you do so at your own risk.
  54  *  This code and its internal interfaces are subject to change or
  55  *  deletion without notice.</b>
  56  */
  57 public class TreeWriter extends AbstractTreeWriter {
  58 
  59     /**
  60      * Packages in this run.
  61      */
  62     SortedSet<PackageElement> packages;
  63 
  64     /**
  65      * True if there are no packages specified on the command line,
  66      * False otherwise.
  67      */
  68     private final boolean classesOnly;
  69 
  70     private final Navigation navBar;
  71 
  72     protected BodyContents bodyContents;
  73 
  74     /**
  75      * Constructor to construct TreeWriter object.
  76      *
  77      * @param configuration the current configuration of the doclet.
  78      * @param filename String filename
  79      * @param classtree the tree being built.
  80      */
  81     public TreeWriter(HtmlConfiguration configuration, DocPath filename, ClassTree classtree) {
  82         super(configuration, filename, classtree);
  83         packages = configuration.packages;
  84         classesOnly = packages.isEmpty();
  85         this.navBar = new Navigation(null, configuration, PageMode.TREE, path);
  86         this.bodyContents = new BodyContents();
  87     }
  88 
  89     /**
  90      * Create a TreeWriter object and use it to generate the
  91      * "overview-tree.html" file.
  92      *
  93      * @param configuration the configuration for this doclet
  94      * @param classtree the class tree being documented.
  95      * @throws  DocFileIOException if there is a problem generating the overview tree page
  96      */
  97     public static void generate(HtmlConfiguration configuration,
  98                                 ClassTree classtree) throws DocFileIOException {
  99         DocPath filename = DocPaths.OVERVIEW_TREE;
 100         TreeWriter treegen = new TreeWriter(configuration, filename, classtree);
 101         treegen.generateTreeFile();
 102     }
 103 
 104     /**
 105      * Generate the interface hierarchy and class hierarchy.
 106      *
 107      * @throws DocFileIOException if there is a problem generating the overview tree page
 108      */
 109     public void generateTreeFile() throws DocFileIOException {
 110         HtmlTree body = getTreeHeader();
 111         Content headContent = contents.hierarchyForAllPackages;
 112         Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING, false,
 113                 HtmlStyle.title, headContent);
 114         Content div = HtmlTree.DIV(HtmlStyle.header, heading);
 115         addPackageTreeLinks(div);
 116         Content mainContent = new ContentBuilder();
 117         mainContent.add(div);
 118         HtmlTree divTree = new HtmlTree(HtmlTag.DIV);
 119         divTree.setStyle(HtmlStyle.contentContainer);
 120         addTree(classtree.baseClasses(), "doclet.Class_Hierarchy", divTree);
 121         addTree(classtree.baseInterfaces(), "doclet.Interface_Hierarchy", divTree);
 122         addTree(classtree.baseAnnotationTypes(), "doclet.Annotation_Type_Hierarchy", divTree);
 123         addTree(classtree.baseEnums(), "doclet.Enum_Hierarchy", divTree, true);
 124         mainContent.add(divTree);
 125         HtmlTree footerTree = HtmlTree.FOOTER();
 126         navBar.setUserFooter(getUserHeaderFooter(false));
 127         footerTree.add(navBar.getContent(false));
 128         addBottom(footerTree);
 129         body.add(bodyContents
 130                 .addMainContent(mainContent)
 131                 .setFooter(footerTree)
 132                 .toContent());
 133         printHtmlDocument(null, "class tree", body);
 134     }
 135 
 136     /**
 137      * Add the links to all the package tree files.
 138      *
 139      * @param contentTree the content tree to which the links will be added
 140      */
 141     protected void addPackageTreeLinks(Content contentTree) {
 142         //Do nothing if only unnamed package is used
 143         if (isUnnamedPackage()) {
 144             return;
 145         }
 146         if (!classesOnly) {
 147             Content span = HtmlTree.SPAN(HtmlStyle.packageHierarchyLabel,
 148                     contents.packageHierarchies);
 149             contentTree.add(span);
 150             HtmlTree ul = new HtmlTree(HtmlTag.UL);
 151             ul.setStyle(HtmlStyle.horizontal);
 152             int i = 0;
 153             for (PackageElement pkg : packages) {
 154                 // If the package name length is 0 or if -nodeprecated option
 155                 // is set and the package is marked as deprecated, do not include
 156                 // the page in the list of package hierarchies.
 157                 if (pkg.isUnnamed() ||
 158                         (configuration.nodeprecated && utils.isDeprecated(pkg))) {
 159                     i++;
 160                     continue;
 161                 }
 162                 DocPath link = pathString(pkg, DocPaths.PACKAGE_TREE);
 163                 Content li = HtmlTree.LI(links.createLink(link,
 164                         new StringContent(utils.getPackageName(pkg))));
 165                 if (i < packages.size() - 1) {
 166                     li.add(", ");
 167                 }
 168                 ul.add(li);
 169                 i++;
 170             }
 171             contentTree.add(ul);
 172         }
 173     }
 174 
 175     /**
 176      * Get the tree header.
 177      *
 178      * @return a content tree for the tree header
 179      */
 180     protected HtmlTree getTreeHeader() {
 181         String title = resources.getText("doclet.Window_Class_Hierarchy");
 182         HtmlTree bodyTree = getBody(getWindowTitle(title));
 183         Content headerContent = new ContentBuilder();
 184         addTop(headerContent);
 185         navBar.setUserHeader(getUserHeaderFooter(true));
 186         headerContent.add(navBar.getContent(true));
 187         bodyContents.setHeader(headerContent);
 188         return bodyTree;
 189     }
 190 
 191     private boolean isUnnamedPackage() {
 192         return packages.size() == 1 && packages.first().isUnnamed();
 193     }
 194 }