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: }