1 /*
2  * Copyright (c) 1998, 2021, 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.*;
29 
30 import javax.lang.model.element.TypeElement;
31 
32 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
33 import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
34 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
35 import jdk.javadoc.internal.doclets.toolkit.Content;
36 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
37 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
38 
39 
40 /**
41  * Abstract class to print the class hierarchy page for all the Classes. This
42  * is sub-classed by {@link PackageTreeWriter} and {@link TreeWriter} to
43  * generate the Package Tree and global Tree(for all the classes and packages)
44  * pages.
45  *
46  *  <p><b>This is NOT part of any supported API.
47  *  If you write code that depends on this, you do so at your own risk.
48  *  This code and its internal interfaces are subject to change or
49  *  deletion without notice.</b>
50  */
51 public abstract class AbstractTreeWriter extends HtmlDocletWriter {
52 
53     /**
54      * The class and interface tree built by using {@link ClassTree}
55      */
56     protected final ClassTree classtree;
57 
58     /**
59      * Constructor initializes classtree variable. This constructor will be used
60      * while generating global tree file "overview-tree.html".
61      *
62      * @param configuration  The current configuration
63      * @param filename   File to be generated.
64      * @param classtree  Tree built by {@link ClassTree}.
65      */
AbstractTreeWriter(HtmlConfiguration configuration, DocPath filename, ClassTree classtree)66     protected AbstractTreeWriter(HtmlConfiguration configuration,
67                                  DocPath filename, ClassTree classtree) {
68         super(configuration, filename);
69         this.classtree = classtree;
70     }
71 
72     /**
73      * Add each level of the class tree. For each sub-class or
74      * sub-interface indents the next level information.
75      * Recurses itself to add sub-classes info.
76      *
77      * @param parent the superclass or superinterface of the sset
78      * @param collection  a collection of the sub-classes at this level
79      * @param isEnum true if we are generating a tree for enums
80      * @param contentTree the content tree to which the level information will be added
81      */
addLevelInfo(TypeElement parent, Collection<TypeElement> collection, boolean isEnum, Content contentTree)82     protected void addLevelInfo(TypeElement parent, Collection<TypeElement> collection,
83             boolean isEnum, Content contentTree) {
84         if (!collection.isEmpty()) {
85             Content ul = new HtmlTree(TagName.UL);
86             for (TypeElement local : collection) {
87                 HtmlTree li = new HtmlTree(TagName.LI);
88                 li.setStyle(HtmlStyle.circle);
89                 addPartialInfo(local, li);
90                 addExtendsImplements(parent, local, li);
91                 addLevelInfo(local, classtree.directSubClasses(local, isEnum),
92                              isEnum, li);   // Recurse
93                 ul.add(li);
94             }
95             contentTree.add(ul);
96         }
97     }
98 
99     /**
100      * Add the heading for the tree depending upon tree type if it's a
101      * Class Tree or Interface tree.
102      *
103      * @param sset classes which are at the most base level, all the
104      * other classes in this run will derive from these classes
105      * @param heading heading for the tree
106      * @param content the content tree to which the tree will be added
107      */
addTree(SortedSet<TypeElement> sset, String heading, Content content)108     protected void addTree(SortedSet<TypeElement> sset, String heading, Content content) {
109         addTree(sset, heading, content, false);
110     }
111 
addTree(SortedSet<TypeElement> sset, String heading, Content content, boolean isEnums)112     protected void addTree(SortedSet<TypeElement> sset, String heading,
113                            Content content, boolean isEnums) {
114         if (!sset.isEmpty()) {
115             TypeElement firstTypeElement = sset.first();
116             Content headingContent = contents.getContent(heading);
117             Content sectionHeading = HtmlTree.HEADING_TITLE(Headings.CONTENT_HEADING,
118                     headingContent);
119             HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.hierarchy, sectionHeading);
120             addLevelInfo(!utils.isInterface(firstTypeElement) ? firstTypeElement : null,
121                     sset, isEnums, htmlTree);
122             content.add(htmlTree);
123         }
124     }
125 
126     /**
127      * Add information regarding the classes which this class extends or
128      * implements.
129      *
130      * @param parent the parent class of the class being documented
131      * @param typeElement the TypeElement under consideration
132      * @param contentTree the content tree to which the information will be added
133      */
addExtendsImplements(TypeElement parent, TypeElement typeElement, Content contentTree)134     protected void addExtendsImplements(TypeElement parent,
135                                         TypeElement typeElement,
136                                         Content contentTree)
137     {
138         SortedSet<TypeElement> interfaces = new TreeSet<>(comparators.makeGeneralPurposeComparator());
139         typeElement.getInterfaces().forEach(t -> interfaces.add(utils.asTypeElement(t)));
140         if (interfaces.size() > (utils.isInterface(typeElement) ? 1 : 0)) {
141             boolean isFirst = true;
142             for (TypeElement intf : interfaces) {
143                 if (parent != intf) {
144                     if (utils.isPublic(intf) || utils.isLinkable(intf)) {
145                         if (isFirst) {
146                             isFirst = false;
147                             if (utils.isInterface(typeElement)) {
148                                 contentTree.add(" (");
149                                 contentTree.add(contents.also);
150                                 contentTree.add(" extends ");
151                             } else {
152                                 contentTree.add(" (implements ");
153                             }
154                         } else {
155                             contentTree.add(", ");
156                         }
157                         addPreQualifiedClassLink(HtmlLinkInfo.Kind.TREE, intf, contentTree);
158                     }
159                 }
160             }
161             if (!isFirst) {
162                 contentTree.add(")");
163             }
164         }
165     }
166 
167     /**
168      * Add information about the class kind, if it's a "class" or "interface".
169      *
170      * @param typeElement the class being documented
171      * @param contentTree the content tree to which the information will be added
172      */
addPartialInfo(TypeElement typeElement, Content contentTree)173     protected void addPartialInfo(TypeElement typeElement, Content contentTree) {
174         addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind.TREE, typeElement, contentTree);
175     }
176 }
177