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