FileDocCategorySizeDatePackage
ClassWriter.javaAPI DocExample14079Wed Apr 19 11:17:10 BST 2000com.sun.tools.doclets.standard

ClassWriter.java

/*
 * @(#)ClassWriter.java	1.45 00/02/02
 *
 * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * This software is the proprietary information of Sun Microsystems, Inc.  
 * Use is subject to license terms.
 * 
 */

package com.sun.tools.doclets.standard;

import com.sun.tools.doclets.*;
import com.sun.javadoc.*;
import java.io.*;
import java.lang.*;
import java.util.*;

/**
 * Generate the Class Information Page.
 * @see com.sun.javadoc.ClassDoc 
 * @see java.util.Collections
 * @see java.util.List
 * @see java.util.ArrayList
 * @see java.util.HashMap
 *
 * @author Atul M Dambalkar
 * @author Robert Field
 */
public class ClassWriter extends SubWriterHolderWriter {

    protected ClassDoc classdoc;

    protected ClassTree classtree;

    protected ClassDoc prev;

    protected ClassDoc next;

    protected boolean nopackage;

    protected MethodSubWriter methodSubWriter;

    protected ConstructorSubWriter constrSubWriter;

    protected FieldSubWriter fieldSubWriter;

    protected ClassSubWriter innerSubWriter;

    public ClassWriter(String path, String filename, ClassDoc classdoc,
                ClassDoc prev, ClassDoc next, ClassTree classtree,
                boolean nopackage) throws IOException, DocletAbortException {
        super(path, filename, 
         DirectoryManager.getRelativePath(classdoc.containingPackage().name()));
        this.classdoc = classdoc;
        HtmlStandardWriter.currentcd = classdoc;
        this.classtree = classtree;
        this.prev = prev;
        this.next = next;
        this.nopackage = nopackage;
        methodSubWriter = new MethodSubWriter(this, classdoc);
        constrSubWriter = new ConstructorSubWriter(this, classdoc);
        fieldSubWriter = new FieldSubWriter(this, classdoc);
        innerSubWriter = new ClassSubWriter(this, classdoc);
    }

    /**
     * Generate a class page.
     *
     * @param prev the previous class to generated, or null if no previous.
     * @param classdoc the class to generate.
     * @param next the next class to be generated, or null if no next.
     */
    public static void generate(ClassDoc classdoc, ClassDoc prev, 
                             ClassDoc next, ClassTree classtree, 
                             boolean nopackage) throws DocletAbortException {
            ClassWriter clsgen;
            String path = 
               DirectoryManager.getDirectoryPath(classdoc.containingPackage());
            String filename = classdoc.name() + ".html";
            try {
                clsgen = new ClassWriter(path, filename, classdoc, 
                                         prev, next, classtree, nopackage);
                clsgen.generateClassFile();
                clsgen.close();
            } catch (IOException exc) {
                Standard.configuration().standardmessage.
                    error("doclet.exception_encountered",
                           exc.toString(), filename);
                throw new DocletAbortException();
            }
    }

    /**
     * Print this package link
     */
    protected void navLinkPackage() {
        navCellStart();
        printHyperLink("package-summary.html", "", getText("doclet.Package"),
                       true, "NavBarFont1");
        navCellEnd();
    }
                                
    /**
     * Print class page indicator
     */
    protected void navLinkClass() {
        navCellRevStart();
        fontStyle("NavBarFont1Rev");
        boldText("doclet.Class");
        fontEnd();
        navCellEnd();
    }

    /**
     * Print class use link
     */
    protected void navLinkClassUse() {
        navCellStart();
        printHyperLink("class-use/" + filename, "", 
                       getText("doclet.navClassUse"), true, "NavBarFont1");
        navCellEnd();
    }

    /**
     * Print previous package link
     */
    protected void navLinkPrevious() {
        if (prev == null) {
            printText("doclet.Prev_Class"); 
        } else {
            printClassLink(prev, getText("doclet.Prev_Class"), true);
        }
    }
                                
    /**
     * Print next package link
     */
    protected void navLinkNext() {
        if (next == null) {
            printText("doclet.Next_Class"); 
        } else {
            printClassLink(next, getText("doclet.Next_Class"), true);
        }
    }                               

    /**
     * Generate the class file contents.
     */
    public void generateClassFile() {
        String cltype = getText(classdoc.isInterface()? 
                                    "doclet.Interface": 
                                    "doclet.Class") + " ";
        PackageDoc pkg = classdoc.containingPackage();
        String pkgname = (pkg != null)? pkg.name(): "";
        String clname = classdoc.name();
        String label = cltype + ' ' + clname;

        printHeader(getText("doclet.Window_ClassFile_label", 
                            Standard.configuration().windowtitle, label));
        navLinks(true);
        hr();
        println("<!-- ======== START OF CLASS DATA ======== -->");
        h2();
        if (pkgname.length() > 0) {
            font("-1"); print(pkgname); fontEnd(); br();
        }
        print(label);
        h2End();

        // if this is a class (not an interface) then generate 
        // the super class tree.
        if (classdoc.isClass()) {
            pre();
            printTreeForClass(classdoc);
            preEnd();
        }
        
        printSuperImplementedInterfacesInfo();

        printSubClassInterfaceInfo();
        
        if (classdoc.isInterface()) {
            printImplementingClasses();
        }

        printEnclosingClassInfo();

        hr();

        printDeprecated();

        printClassDescription();
        p();
        // generate documentation for the class.
        if (classdoc.inlineTags().length > 0) {
            printInlineComment(classdoc);
            p();
        }
        // Print Information about all the tags here
        generateTagInfo(classdoc);
        hr();
        p();

	printAllMembers();

        println("<!-- ========= END OF CLASS DATA ========= -->");
        hr();
        navLinks(false);
        printBottom();
        printBodyHtmlEnd();
    }

    /**
     * Print summary and detail information for the specified members in the 
     * class.
     */
    protected void printAllMembers() {
        println("<!-- ======== INNER CLASS SUMMARY ======== -->"); println();
	innerSubWriter.printMembersSummary();
	innerSubWriter.printInheritedMembersSummary();
        println(); 
        println("<!-- =========== FIELD SUMMARY =========== -->"); println();
	fieldSubWriter.printMembersSummary();
	fieldSubWriter.printInheritedMembersSummary();
        println(); 
        println("<!-- ======== CONSTRUCTOR SUMMARY ======== -->"); println();
	constrSubWriter.printMembersSummary();
        println(); 
        println("<!-- ========== METHOD SUMMARY =========== -->"); println();
	methodSubWriter.printMembersSummary();
        methodSubWriter.printInheritedMembersSummary();

        p();

        println(); 
        println("<!-- ============ FIELD DETAIL =========== -->"); println();
	fieldSubWriter.printMembers();
        println(); 
        println("<!-- ========= CONSTRUCTOR DETAIL ======== -->"); println();
	constrSubWriter.printMembers();
        println(); 
        println("<!-- ============ METHOD DETAIL ========== -->"); println();
	methodSubWriter.printMembers();
    }


    /**
     * Print the class description regarding iterfaces implemented, classes
     * inheritted.
     */
    protected void printClassDescription() {
        boolean isInterface = classdoc.isInterface();
        dl();
        dt();

        print(classdoc.modifiers() + " ");  

        if (!isInterface) {
            print("class ");
        }
        bold(classdoc.name());

        if (!isInterface) {
            ClassDoc superclass = classdoc.superclass();
            if (superclass != null) {
                dt();
                print("extends ");
                printClassLink(superclass); 
            }
        }

        ClassDoc[] implIntfacs = classdoc.interfaces();
        if (implIntfacs != null && implIntfacs.length > 0) {
            dt();
            print(isInterface? "extends " : "implements ");
            printClassLink(implIntfacs[0]);
            for (int i = 1; i < implIntfacs.length; i++) {
                print(", ");
                printClassLink(implIntfacs[i]);
            }
        }
        dlEnd();
    }
  
    /**
     * Mark the class as deprecated if it is.
     */
    protected void printDeprecated() {
        Tag[] deprs = classdoc.tags("deprecated");
        if (deprs.length > 0) {
            Tag[] commentTags = deprs[0].inlineTags();
            if (commentTags.length > 0) {
                boldText("doclet.Deprecated");
                space();
                printInlineDeprecatedComment(deprs[0]);
            }
            p();
        }
    }

    /**
     * Generate the step like diagram for the class hierarchy.
     */
    protected void printStep(int indent) {
        String spc = spaces(6 * indent - 4);
        print(spc);
        println("|");
        print(spc);
        print("+--");
    }

    /**
     * Print the class hierarchy tree for this class only.
     */
    protected int printTreeForClass(ClassDoc cd) {
        ClassDoc sup = cd.superclass();
        int indent = 0;
        if (sup != null) {
            indent = printTreeForClass(sup);
            printStep(indent);
        }
        if (cd.equals(classdoc)) {
            bold(cd.qualifiedName());
        } else {
            printQualifiedClassLink(cd);
        }
        println();
        return indent + 1;
    }

    /**
     * Which are the sub-classes or sub-interfaces for this class?
     */ 
    protected void printSubClassInterfaceInfo() {
        // Before using TreeBuilder.getSubClassList
        // make sure that tree.html is generated prior.
        if (classdoc.qualifiedName().equals("java.lang.Object") ||
               classdoc.qualifiedName().equals("org.omg.CORBA.Object")) {
            return;    // Don't generate the list, too huge
        }
        List subclasses = classdoc.isClass()? 
                             classtree.subs(classdoc): // it's a class
                             classtree.allSubs(classdoc); // it's an interface
        if (subclasses.size() > 0) {
            printInfoHeader();
            if (classdoc.isClass()) {
                boldText("doclet.Subclasses");
            } else { // this is an interface
                boldText("doclet.Subinterfaces");
            }
            printSubClassLinkInfo(subclasses);
        }
    }

    /**
     * If this is the interface which are the classes, that implement this?
     */
    protected void printImplementingClasses() {
        if (classdoc.qualifiedName().equals("java.lang.Cloneable") || 
                classdoc.qualifiedName().equals("java.io.Serializable")) {
            return;   // Don't generate the list, too big
        }
        List implcl = classtree.implementingclasses(classdoc);
        if (implcl.size() > 0) {
            printInfoHeader();
            boldText("doclet.Implementing_Classes");
            printSubClassLinkInfo(implcl);
        }
    }

    protected void printSuperImplementedInterfacesInfo() {
        ProgramElementDoc[] intarr = Util.getAllInterfaces(classdoc);
        Arrays.sort(intarr);
        if (intarr.length > 0) {
            printInfoHeader();
            boldText(classdoc.isClass()?
		         "doclet.All_Implemented_Interfaces":
                         "doclet.All_Superinterfaces");
            printSubClassLinkInfo(Arrays.asList(intarr));
        }
    }   

    protected void printInfoHeader() {
        dl();
        dt();
    }

    /**
     * Generate a link for the sub-classes.
     */
    protected void printSubClassLinkInfo(List list) {
        int i = 0;
        print(' ');
        dd();
        for (; i < list.size() - 1; i++) {
            printClassLink((ClassDoc)(list.get(i)));
            print(", ");
        }
        printClassLink((ClassDoc)(list.get(i)));
        ddEnd();
        dlEnd();
    }

    protected void navLinkTree() {
        navCellStart();
        if (nopackage) {
            printHyperLink(relativepath + "overview-tree.html", "",
                           getText("doclet.Tree"), true, "NavBarFont1");
        } else {
            printHyperLink("package-tree.html", "", getText("doclet.Tree"),
                           true, "NavBarFont1");
        }
        navCellEnd();
    }

    protected void printSummaryDetailLinks() {
        tr();
        tdVAlignClass("top", "NavBarCell3");
        font("-2");
        print("  ");
        navSummaryLinks();
        fontEnd();
        tdEnd();
        
        tdVAlignClass("top", "NavBarCell3");
        font("-2");
        navDetailLinks();
        fontEnd();
        tdEnd();
        trEnd();
    }   

    protected void navSummaryLinks() {
        printText("doclet.Summary");
        print(" ");
        innerSubWriter.navSummaryLink();
        navGap();
        fieldSubWriter.navSummaryLink();
        navGap();
        constrSubWriter.navSummaryLink();
        navGap();
        methodSubWriter.navSummaryLink();
    }

    protected void navDetailLinks() {
        printText("doclet.Detail");
        print(" ");
        fieldSubWriter.navDetailLink();
        navGap();
        constrSubWriter.navDetailLink();
        navGap();
        methodSubWriter.navDetailLink();
    }

    protected void navGap() {
        space();
        print('|');
        space();
    }

    protected void printEnclosingClassInfo() {
        ClassDoc outerClass = classdoc.containingClass(); 
        if (outerClass != null) {
            printInfoHeader();
            boldText("doclet.Enclosing_Class");
            dd();
            printClassLink(outerClass);            
            ddEnd();
            dlEnd();
        }
    }
}