duke@1: /* ohair@554: * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.doclets.formats.html; duke@1: bpatel@233: import java.util.*; bpatel@233: bpatel@233: import com.sun.javadoc.*; duke@1: import com.sun.tools.doclets.internal.toolkit.*; duke@1: import com.sun.tools.doclets.internal.toolkit.util.*; duke@1: import com.sun.tools.doclets.internal.toolkit.builders.*; duke@1: import com.sun.tools.doclets.internal.toolkit.taglets.*; duke@1: duke@1: /** duke@1: * Generate the Class Information Page. duke@1: * @see com.sun.javadoc.ClassDoc duke@1: * @see java.util.Collections duke@1: * @see java.util.List duke@1: * @see java.util.ArrayList duke@1: * @see java.util.HashMap duke@1: * duke@1: * @author Atul M Dambalkar duke@1: * @author Robert Field duke@1: */ duke@1: public class ClassWriterImpl extends SubWriterHolderWriter duke@1: implements ClassWriter { duke@1: duke@1: protected ClassDoc classDoc; duke@1: duke@1: protected ClassTree classtree; duke@1: duke@1: protected ClassDoc prev; duke@1: duke@1: protected ClassDoc next; duke@1: duke@1: /** duke@1: * @param classDoc the class being documented. duke@1: * @param prevClass the previous class that was documented. duke@1: * @param nextClass the next class being documented. duke@1: * @param classTree the class tree for the given class. duke@1: */ duke@1: public ClassWriterImpl (ClassDoc classDoc, duke@1: ClassDoc prevClass, ClassDoc nextClass, ClassTree classTree) duke@1: throws Exception { duke@1: super(ConfigurationImpl.getInstance(), duke@1: DirectoryManager.getDirectoryPath(classDoc.containingPackage()), duke@1: classDoc.name() + ".html", duke@1: DirectoryManager.getRelativePath(classDoc.containingPackage().name())); duke@1: this.classDoc = classDoc; duke@1: configuration.currentcd = classDoc; duke@1: this.classtree = classTree; duke@1: this.prev = prevClass; duke@1: this.next = nextClass; duke@1: } duke@1: duke@1: /** duke@1: * Print this package link duke@1: */ duke@1: protected void navLinkPackage() { duke@1: navCellStart(); duke@1: printHyperLink("package-summary.html", "", duke@1: configuration.getText("doclet.Package"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** duke@1: * Print class page indicator duke@1: */ duke@1: protected void navLinkClass() { duke@1: navCellRevStart(); duke@1: fontStyle("NavBarFont1Rev"); bpatel@182: strongText("doclet.Class"); duke@1: fontEnd(); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** duke@1: * Print class use link duke@1: */ duke@1: protected void navLinkClassUse() { duke@1: navCellStart(); duke@1: printHyperLink("class-use/" + filename, "", duke@1: configuration.getText("doclet.navClassUse"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: /** duke@1: * Print previous package link duke@1: */ duke@1: protected void navLinkPrevious() { duke@1: if (prev == null) { duke@1: printText("doclet.Prev_Class"); duke@1: } else { duke@1: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, prev, "", duke@1: configuration.getText("doclet.Prev_Class"), true)); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Print next package link duke@1: */ duke@1: protected void navLinkNext() { duke@1: if (next == null) { duke@1: printText("doclet.Next_Class"); duke@1: } else { duke@1: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, next, "", duke@1: configuration.getText("doclet.Next_Class"), true)); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeHeader(String header) { duke@1: String pkgname = (classDoc.containingPackage() != null)? duke@1: classDoc.containingPackage().name(): ""; duke@1: String clname = classDoc.name(); duke@1: printHtmlHeader(clname, duke@1: configuration.metakeywords.getMetaKeywords(classDoc), true); duke@1: printTop(); duke@1: navLinks(true); duke@1: hr(); duke@1: println(""); duke@1: h2(); duke@1: if (pkgname.length() > 0) { duke@1: font("-1"); print(pkgname); fontEnd(); br(); duke@1: } duke@1: LinkInfoImpl linkInfo = new LinkInfoImpl( LinkInfoImpl.CONTEXT_CLASS_HEADER, duke@1: classDoc, false); duke@1: //Let's not link to ourselves in the header. duke@1: linkInfo.linkToSelf = false; duke@1: print(header + getTypeParameterLinks(linkInfo)); duke@1: h2End(); duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeFooter() { duke@1: println(""); duke@1: hr(); duke@1: navLinks(false); duke@1: printBottom(); duke@1: printBodyHtmlEnd(); duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeClassSignature(String modifiers) { duke@1: boolean isInterface = classDoc.isInterface(); duke@1: preNoNewLine(); duke@1: writeAnnotationInfo(classDoc); duke@1: print(modifiers); duke@1: LinkInfoImpl linkInfo = new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE, classDoc, false); duke@1: //Let's not link to ourselves in the signature. duke@1: linkInfo.linkToSelf = false; duke@1: String name = classDoc.name() + duke@1: getTypeParameterLinks(linkInfo); duke@1: if (configuration().linksource) { duke@1: printSrcLink(classDoc, name); duke@1: } else { bpatel@182: strong(name); duke@1: } duke@1: if (!isInterface) { duke@1: Type superclass = Util.getFirstVisibleSuperClass(classDoc, duke@1: configuration()); duke@1: if (superclass != null) { bpatel@233: println(); duke@1: print("extends "); duke@1: printLink(new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, duke@1: superclass)); duke@1: } duke@1: } duke@1: Type[] implIntfacs = classDoc.interfaceTypes(); duke@1: if (implIntfacs != null && implIntfacs.length > 0) { duke@1: int counter = 0; duke@1: for (int i = 0; i < implIntfacs.length; i++) { duke@1: ClassDoc classDoc = implIntfacs[i].asClassDoc(); duke@1: if (! (classDoc.isPublic() || duke@1: Util.isLinkable(classDoc, configuration()))) { duke@1: continue; duke@1: } duke@1: if (counter == 0) { bpatel@233: println(); duke@1: print(isInterface? "extends " : "implements "); duke@1: } else { duke@1: print(", "); duke@1: } duke@1: printLink(new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_CLASS_SIGNATURE_PARENT_NAME, duke@1: implIntfacs[i])); duke@1: counter++; duke@1: } duke@1: } duke@1: preEnd(); duke@1: p(); duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeClassDescription() { duke@1: if(!configuration.nocomment) { duke@1: // generate documentation for the class. duke@1: if (classDoc.inlineTags().length > 0) { duke@1: printInlineComment(classDoc); duke@1: p(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeClassTagInfo() { duke@1: if(!configuration.nocomment) { duke@1: // Print Information about all the tags here duke@1: printTags(classDoc); duke@1: hr(); duke@1: p(); duke@1: } else { duke@1: hr(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeClassDeprecationInfo() { duke@1: hr(); duke@1: Tag[] deprs = classDoc.tags("deprecated"); duke@1: if (Util.isDeprecated(classDoc)) { bpatel@182: strongText("doclet.Deprecated"); duke@1: if (deprs.length > 0) { duke@1: Tag[] commentTags = deprs[0].inlineTags(); duke@1: if (commentTags.length > 0) { duke@1: space(); duke@1: printInlineDeprecatedComment(classDoc, deprs[0]); duke@1: } duke@1: } duke@1: p(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Generate the indent and get the line image for the class tree. duke@1: * For user accessibility, the image includes the alt attribute duke@1: * "extended by". (This method is not intended for a class duke@1: * implementing an interface, where "implemented by" would be required.) duke@1: * duke@1: * indent integer indicating the number of spaces to indent duke@1: */ duke@1: private void writeStep(int indent) { duke@1: print(spaces(4 * indent - 2)); duke@1: print(""); duke@1: } duke@1: duke@1: /** duke@1: * Print the class hierarchy tree for the given class. duke@1: * @param type the class to print the hierarchy for. duke@1: * @return return the amount that should be indented in duke@1: * the next level of the tree. duke@1: */ duke@1: private int writeTreeForClassHelper(Type type) { duke@1: Type sup = Util.getFirstVisibleSuperClass( duke@1: type instanceof ClassDoc ? (ClassDoc) type : type.asClassDoc(), duke@1: configuration()); duke@1: int indent = 0; duke@1: if (sup != null) { duke@1: indent = writeTreeForClassHelper(sup); duke@1: writeStep(indent); duke@1: } duke@1: duke@1: if (type.equals(classDoc)) { duke@1: String typeParameters = getTypeParameterLinks( duke@1: new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_TREE, duke@1: classDoc, false)); duke@1: if (configuration.shouldExcludeQualifier( duke@1: classDoc.containingPackage().name())) { bpatel@182: strong(type.asClassDoc().name() + typeParameters); duke@1: } else { bpatel@182: strong(type.asClassDoc().qualifiedName() + typeParameters); duke@1: } duke@1: } else { duke@1: print(getLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS_TREE_PARENT, duke@1: type instanceof ClassDoc ? (ClassDoc) type : type, duke@1: configuration.getClassName(type.asClassDoc()), false))); duke@1: } duke@1: println(); duke@1: return indent + 1; duke@1: } duke@1: duke@1: /** duke@1: * Print the class hierarchy tree for this class only. duke@1: */ duke@1: public void writeClassTree() { duke@1: if (! classDoc.isClass()) { duke@1: return; duke@1: } duke@1: pre(); duke@1: writeTreeForClassHelper(classDoc); duke@1: preEnd(); duke@1: } duke@1: duke@1: /** duke@1: * Write the type parameter information. duke@1: */ duke@1: public void writeTypeParamInfo() { duke@1: if (classDoc.typeParamTags().length > 0) { duke@1: dl(); duke@1: dt(); duke@1: TagletOutput output = (new ParamTaglet()).getTagletOutput(classDoc, duke@1: getTagletWriterInstance(false)); duke@1: print(output.toString()); bpatel@233: dtEnd(); duke@1: dlEnd(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeSubClassInfo() { duke@1: if (classDoc.isClass()) { duke@1: if (classDoc.qualifiedName().equals("java.lang.Object") || duke@1: classDoc.qualifiedName().equals("org.omg.CORBA.Object")) { duke@1: return; // Don't generate the list, too huge duke@1: } mcimadamore@184: List subclasses = classtree.subs(classDoc, false); duke@1: if (subclasses.size() > 0) { duke@1: dl(); duke@1: dt(); bpatel@182: strongText("doclet.Subclasses"); bpatel@233: dtEnd(); duke@1: writeClassLinks(LinkInfoImpl.CONTEXT_SUBCLASSES, duke@1: subclasses); bpatel@233: dlEnd(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeSubInterfacesInfo() { duke@1: if (classDoc.isInterface()) { mcimadamore@184: List subInterfaces = classtree.allSubs(classDoc, false); duke@1: if (subInterfaces.size() > 0) { duke@1: dl(); duke@1: dt(); bpatel@182: strongText("doclet.Subinterfaces"); bpatel@233: dtEnd(); duke@1: writeClassLinks(LinkInfoImpl.CONTEXT_SUBINTERFACES, duke@1: subInterfaces); bpatel@233: dlEnd(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * If this is the interface which are the classes, that implement this? duke@1: */ duke@1: public void writeInterfaceUsageInfo () { duke@1: if (! classDoc.isInterface()) { duke@1: return; duke@1: } duke@1: if (classDoc.qualifiedName().equals("java.lang.Cloneable") || duke@1: classDoc.qualifiedName().equals("java.io.Serializable")) { duke@1: return; // Don't generate the list, too big duke@1: } mcimadamore@184: List implcl = classtree.implementingclasses(classDoc); duke@1: if (implcl.size() > 0) { duke@1: dl(); duke@1: dt(); bpatel@182: strongText("doclet.Implementing_Classes"); bpatel@233: dtEnd(); duke@1: writeClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_CLASSES, duke@1: implcl); bpatel@233: dlEnd(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeImplementedInterfacesInfo() { duke@1: //NOTE: we really should be using ClassDoc.interfaceTypes() here, but duke@1: // it doesn't walk up the tree like we want it to. mcimadamore@184: List interfaceArray = Util.getAllInterfaces(classDoc, configuration); duke@1: if (classDoc.isClass() && interfaceArray.size() > 0) { duke@1: dl(); duke@1: dt(); bpatel@182: strongText("doclet.All_Implemented_Interfaces"); bpatel@233: dtEnd(); duke@1: writeClassLinks(LinkInfoImpl.CONTEXT_IMPLEMENTED_INTERFACES, duke@1: interfaceArray); bpatel@233: dlEnd(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeSuperInterfacesInfo() { duke@1: //NOTE: we really should be using ClassDoc.interfaceTypes() here, but duke@1: // it doesn't walk up the tree like we want it to. mcimadamore@184: List interfaceArray = Util.getAllInterfaces(classDoc, configuration); duke@1: if (classDoc.isInterface() && interfaceArray.size() > 0) { duke@1: dl(); duke@1: dt(); bpatel@182: strongText("doclet.All_Superinterfaces"); bpatel@233: dtEnd(); duke@1: writeClassLinks(LinkInfoImpl.CONTEXT_SUPER_INTERFACES, duke@1: interfaceArray); bpatel@233: dlEnd(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Generate links to the given classes. duke@1: */ mcimadamore@184: private void writeClassLinks(int context, List list) { duke@1: Object[] typeList = list.toArray(); duke@1: //Sort the list to be printed. duke@1: print(' '); duke@1: dd(); duke@1: for (int i = 0; i < list.size(); i++) { duke@1: if (i > 0) { duke@1: print(", "); duke@1: } duke@1: if (typeList[i] instanceof ClassDoc) { duke@1: printLink(new LinkInfoImpl(context, (ClassDoc)(typeList[i]))); duke@1: duke@1: } else { duke@1: printLink(new LinkInfoImpl(context, (Type)(typeList[i]))); duke@1: } duke@1: } duke@1: ddEnd(); duke@1: } duke@1: duke@1: protected void navLinkTree() { duke@1: navCellStart(); duke@1: printHyperLink("package-tree.html", "", duke@1: configuration.getText("doclet.Tree"), true, "NavBarFont1"); duke@1: navCellEnd(); duke@1: } duke@1: duke@1: protected void printSummaryDetailLinks() { duke@1: try { duke@1: tr(); duke@1: tdVAlignClass("top", "NavBarCell3"); duke@1: font("-2"); duke@1: print(" "); duke@1: navSummaryLinks(); duke@1: fontEnd(); duke@1: tdEnd(); duke@1: tdVAlignClass("top", "NavBarCell3"); duke@1: font("-2"); duke@1: navDetailLinks(); duke@1: fontEnd(); duke@1: tdEnd(); duke@1: trEnd(); duke@1: } catch (Exception e) { duke@1: e.printStackTrace(); duke@1: throw new DocletAbortException(); duke@1: } duke@1: } duke@1: duke@1: protected void navSummaryLinks() throws Exception { duke@1: printText("doclet.Summary"); duke@1: space(); duke@1: MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) duke@1: configuration.getBuilderFactory().getMemberSummaryBuilder(this); duke@1: String[] navLinkLabels = new String[] { duke@1: "doclet.navNested", "doclet.navEnum", "doclet.navField", "doclet.navConstructor", duke@1: "doclet.navMethod" duke@1: }; duke@1: for (int i = 0; i < navLinkLabels.length; i++ ) { duke@1: if (i == VisibleMemberMap.ENUM_CONSTANTS && ! classDoc.isEnum()) { duke@1: continue; duke@1: } duke@1: if (i == VisibleMemberMap.CONSTRUCTORS && classDoc.isEnum()) { duke@1: continue; duke@1: } duke@1: AbstractMemberWriter writer = duke@1: ((AbstractMemberWriter) memberSummaryBuilder. duke@1: getMemberSummaryWriter(i)); duke@1: if (writer == null) { duke@1: printText(navLinkLabels[i]); duke@1: } else { duke@1: writer.navSummaryLink( duke@1: memberSummaryBuilder.members(i), duke@1: memberSummaryBuilder.getVisibleMemberMap(i)); duke@1: } duke@1: if (i < navLinkLabels.length-1) { duke@1: navGap(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Method navDetailLinks duke@1: * duke@1: * @throws Exception duke@1: * duke@1: */ duke@1: protected void navDetailLinks() throws Exception { duke@1: printText("doclet.Detail"); duke@1: space(); duke@1: MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) duke@1: configuration.getBuilderFactory().getMemberSummaryBuilder(this); duke@1: String[] navLinkLabels = new String[] { duke@1: "doclet.navNested", "doclet.navEnum", "doclet.navField", "doclet.navConstructor", duke@1: "doclet.navMethod" duke@1: }; duke@1: for (int i = 1; i < navLinkLabels.length; i++ ) { duke@1: AbstractMemberWriter writer = duke@1: ((AbstractMemberWriter) memberSummaryBuilder. duke@1: getMemberSummaryWriter(i)); duke@1: if (i == VisibleMemberMap.ENUM_CONSTANTS && ! classDoc.isEnum()) { duke@1: continue; duke@1: } duke@1: if (i == VisibleMemberMap.CONSTRUCTORS && classDoc.isEnum()) { duke@1: continue; duke@1: } duke@1: if (writer == null) { duke@1: printText(navLinkLabels[i]); duke@1: } else { duke@1: writer.navDetailLink(memberSummaryBuilder.members(i)); duke@1: } duke@1: if (i < navLinkLabels.length - 1) { duke@1: navGap(); duke@1: } duke@1: } duke@1: } duke@1: duke@1: protected void navGap() { duke@1: space(); duke@1: print('|'); duke@1: space(); duke@1: } duke@1: duke@1: /** duke@1: * If this is an inner class or interface, write the enclosing class or duke@1: * interface. duke@1: */ duke@1: public void writeNestedClassInfo() { duke@1: ClassDoc outerClass = classDoc.containingClass(); duke@1: if (outerClass != null) { duke@1: dl(); duke@1: dt(); duke@1: if (outerClass.isInterface()) { bpatel@182: strongText("doclet.Enclosing_Interface"); duke@1: } else { bpatel@182: strongText("doclet.Enclosing_Class"); duke@1: } bpatel@233: dtEnd(); duke@1: dd(); duke@1: printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_CLASS, outerClass, duke@1: false)); duke@1: ddEnd(); duke@1: dlEnd(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Return the classDoc being documented. duke@1: * duke@1: * @return the classDoc being documented. duke@1: */ duke@1: public ClassDoc getClassDoc() { duke@1: return classDoc; duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void completeMemberSummaryBuild() { duke@1: p(); duke@1: } duke@1: }