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