duke@1: /* xdono@117: * Copyright 1997-2008 Sun Microsystems, Inc. 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 duke@1: * published by the Free Software Foundation. Sun designates this duke@1: * particular file as subject to the "Classpath" exception as provided duke@1: * by Sun 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: * duke@1: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@1: * CA 95054 USA or visit www.sun.com if you need additional information or duke@1: * have any questions. duke@1: */ duke@1: duke@1: package com.sun.tools.doclets.formats.html; duke@1: duke@1: import com.sun.tools.doclets.internal.toolkit.util.*; duke@1: import com.sun.tools.doclets.internal.toolkit.taglets.*; duke@1: duke@1: import com.sun.javadoc.*; duke@1: import java.util.*; duke@1: import java.lang.reflect.Modifier; duke@1: duke@1: /** duke@1: * The base class for member writers. duke@1: * duke@1: * @author Robert Field duke@1: * @author Atul M Dambalkar duke@1: * @author Jamie Ho (Re-write) duke@1: */ duke@1: public abstract class AbstractMemberWriter { duke@1: duke@1: protected boolean printedSummaryHeader = false; duke@1: protected final SubWriterHolderWriter writer; duke@1: protected final ClassDoc classdoc; duke@1: public final boolean nodepr; duke@1: duke@1: public AbstractMemberWriter(SubWriterHolderWriter writer, duke@1: ClassDoc classdoc) { duke@1: this.writer = writer; duke@1: this.nodepr = configuration().nodeprecated; duke@1: this.classdoc = classdoc; duke@1: } duke@1: duke@1: public AbstractMemberWriter(SubWriterHolderWriter writer) { duke@1: this(writer, null); duke@1: } duke@1: duke@1: /*** abstracts ***/ duke@1: duke@1: public abstract void printSummaryLabel(ClassDoc cd); duke@1: duke@1: public abstract void printInheritedSummaryLabel(ClassDoc cd); duke@1: duke@1: public abstract void printSummaryAnchor(ClassDoc cd); duke@1: duke@1: public abstract void printInheritedSummaryAnchor(ClassDoc cd); duke@1: duke@1: protected abstract void printSummaryType(ProgramElementDoc member); duke@1: duke@1: protected void writeSummaryLink(ClassDoc cd, ProgramElementDoc member) { duke@1: writeSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member); duke@1: } duke@1: duke@1: protected abstract void writeSummaryLink(int context, duke@1: ClassDoc cd, duke@1: ProgramElementDoc member); duke@1: duke@1: protected abstract void writeInheritedSummaryLink(ClassDoc cd, duke@1: ProgramElementDoc member); duke@1: duke@1: protected abstract void writeDeprecatedLink(ProgramElementDoc member); duke@1: duke@1: protected abstract void printNavSummaryLink(ClassDoc cd, boolean link); duke@1: duke@1: protected abstract void printNavDetailLink(boolean link); duke@1: duke@1: /*** ***/ duke@1: duke@1: protected void print(String str) { duke@1: writer.print(str); duke@1: writer.displayLength += str.length(); duke@1: } duke@1: duke@1: protected void print(char ch) { duke@1: writer.print(ch); duke@1: writer.displayLength++; duke@1: } duke@1: bpatel@182: protected void strong(String str) { bpatel@182: writer.strong(str); duke@1: writer.displayLength += str.length(); duke@1: } duke@1: duke@1: /** duke@1: * Return a string describing the access modifier flags. duke@1: * Don't include native or synchronized. duke@1: * duke@1: * The modifier names are returned in canonical order, as duke@1: * specified by The Java Language Specification. duke@1: */ duke@1: protected String modifierString(MemberDoc member) { duke@1: int ms = member.modifierSpecifier(); duke@1: int no = Modifier.NATIVE | Modifier.SYNCHRONIZED; duke@1: return Modifier.toString(ms & ~no); duke@1: } duke@1: duke@1: protected String typeString(MemberDoc member) { duke@1: String type = ""; duke@1: if (member instanceof MethodDoc) { duke@1: type = ((MethodDoc)member).returnType().toString(); duke@1: } else if (member instanceof FieldDoc) { duke@1: type = ((FieldDoc)member).type().toString(); duke@1: } duke@1: return type; duke@1: } duke@1: duke@1: protected void printModifiers(MemberDoc member) { duke@1: String mod = modifierString(member); duke@1: // According to JLS, we should not be showing public modifier for duke@1: // interface methods. duke@1: if ((member.isField() || member.isMethod()) && duke@1: writer instanceof ClassWriterImpl && duke@1: ((ClassWriterImpl) writer).getClassDoc().isInterface()) { duke@1: mod = Util.replaceText(mod, "public", "").trim(); duke@1: } duke@1: if(mod.length() > 0) { duke@1: print(mod); duke@1: print(' '); duke@1: } duke@1: } duke@1: duke@1: protected String makeSpace(int len) { duke@1: if (len <= 0) { duke@1: return ""; duke@1: } duke@1: StringBuffer sb = new StringBuffer(len); duke@1: for(int i = 0; i < len; i++) { duke@1: sb.append(' '); duke@1: } duke@1: return sb.toString(); duke@1: } duke@1: duke@1: /** duke@1: * Print 'static' if static and type link. duke@1: */ duke@1: protected void printStaticAndType(boolean isStatic, Type type) { duke@1: writer.printTypeSummaryHeader(); duke@1: if (isStatic) { duke@1: print("static"); duke@1: } duke@1: writer.space(); duke@1: if (type != null) { duke@1: writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER, duke@1: type)); duke@1: } duke@1: writer.printTypeSummaryFooter(); duke@1: } duke@1: duke@1: /** duke@1: * Print the modifier and type for the member in the member summary. duke@1: * duke@1: * @param member the member to print the type for. duke@1: * @param type the type to print. duke@1: */ duke@1: protected void printModifierAndType(ProgramElementDoc member, Type type) { duke@1: writer.printTypeSummaryHeader(); duke@1: printModifier(member); duke@1: if (type == null) { duke@1: writer.space(); duke@1: if (member.isClass()) { duke@1: print("class"); duke@1: } else { duke@1: print("interface"); duke@1: } duke@1: } else { duke@1: if (member instanceof ExecutableMemberDoc && duke@1: ((ExecutableMemberDoc) member).typeParameters().length > 0) { duke@1: //Code to avoid ugly wrapping in member summary table. duke@1: writer.table(0,0,0); duke@1: writer.trAlignVAlign("right", ""); duke@1: writer.tdNowrap(); duke@1: writer.font("-1"); duke@1: writer.code(); duke@1: int displayLength = ((AbstractExecutableMemberWriter) this). duke@1: writeTypeParameters((ExecutableMemberDoc) member); duke@1: if (displayLength > 10) { duke@1: writer.br(); duke@1: } duke@1: writer.printLink(new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)); duke@1: writer.codeEnd(); duke@1: writer.fontEnd(); duke@1: writer.tdEnd(); duke@1: writer.trEnd(); duke@1: writer.tableEnd(); duke@1: } else { duke@1: writer.space(); duke@1: writer.printLink(new LinkInfoImpl( duke@1: LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type)); duke@1: } duke@1: duke@1: } duke@1: writer.printTypeSummaryFooter(); duke@1: } duke@1: duke@1: private void printModifier(ProgramElementDoc member) { duke@1: if (member.isProtected()) { duke@1: print("protected "); duke@1: } else if (member.isPrivate()) { duke@1: print("private "); duke@1: } else if (!member.isPublic()) { // Package private duke@1: writer.printText("doclet.Package_private"); duke@1: print(" "); duke@1: } duke@1: if (member.isMethod() && ((MethodDoc)member).isAbstract()) { duke@1: print("abstract "); duke@1: } duke@1: if (member.isStatic()) { duke@1: print("static"); duke@1: } duke@1: } duke@1: duke@1: protected void printComment(ProgramElementDoc member) { duke@1: if (member.inlineTags().length > 0) { duke@1: writer.dd(); duke@1: writer.printInlineComment(member); duke@1: } duke@1: } duke@1: duke@1: protected String name(ProgramElementDoc member) { duke@1: return member.name(); duke@1: } duke@1: duke@1: protected void printHead(MemberDoc member) { duke@1: writer.h3(); duke@1: writer.print(member.name()); duke@1: writer.h3End(); duke@1: } duke@1: duke@1: protected void printFullComment(ProgramElementDoc member) { duke@1: if(configuration().nocomment){ duke@1: return; duke@1: } duke@1: writer.dl(); duke@1: print(((TagletOutputImpl) duke@1: (new DeprecatedTaglet()).getTagletOutput(member, duke@1: writer.getTagletWriterInstance(false))).toString()); duke@1: printCommentAndTags(member); duke@1: writer.dlEnd(); duke@1: } duke@1: duke@1: protected void printCommentAndTags(ProgramElementDoc member) { duke@1: printComment(member); duke@1: writer.printTags(member); duke@1: } duke@1: duke@1: /** duke@1: * Forward to containing writer duke@1: */ duke@1: public void printSummaryHeader(ClassDoc cd) { duke@1: printedSummaryHeader = true; duke@1: writer.printSummaryHeader(this, cd); duke@1: } duke@1: duke@1: /** duke@1: * Forward to containing writer duke@1: */ duke@1: public void printInheritedSummaryHeader(ClassDoc cd) { duke@1: writer.printInheritedSummaryHeader(this, cd); duke@1: } duke@1: duke@1: /** duke@1: * Forward to containing writer duke@1: */ duke@1: public void printInheritedSummaryFooter(ClassDoc cd) { duke@1: writer.printInheritedSummaryFooter(this, cd); duke@1: } duke@1: duke@1: /** duke@1: * Forward to containing writer duke@1: */ duke@1: public void printSummaryFooter(ClassDoc cd) { duke@1: writer.printSummaryFooter(this, cd); duke@1: } duke@1: duke@1: /** duke@1: * Return true if the given ProgramElement is inherited duke@1: * by the class that is being documented. duke@1: * duke@1: * @param ped The ProgramElement being checked. duke@1: * return true if the ProgramElement is being inherited and duke@1: * false otherwise. duke@1: */ duke@1: protected boolean isInherited(ProgramElementDoc ped){ duke@1: if(ped.isPrivate() || (ped.isPackagePrivate() && duke@1: ! ped.containingPackage().equals(classdoc.containingPackage()))){ duke@1: return false; duke@1: } duke@1: return true; duke@1: } duke@1: duke@1: duke@1: /** duke@1: * Generate the code for listing the deprecated APIs. Create the table duke@1: * format for listing the API. Call methods from the sub-class to complete duke@1: * the generation. duke@1: */ duke@1: protected void printDeprecatedAPI(List deprmembers, String headingKey) { duke@1: if (deprmembers.size() > 0) { duke@1: writer.tableIndexSummary(); duke@1: writer.tableHeaderStart("#CCCCFF"); bpatel@182: writer.strongText(headingKey); duke@1: writer.tableHeaderEnd(); duke@1: for (int i = 0; i < deprmembers.size(); i++) { duke@1: ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i); duke@1: writer.trBgcolorStyle("white", "TableRowColor"); duke@1: writer.summaryRow(0); duke@1: writeDeprecatedLink(member); duke@1: writer.br(); duke@1: writer.printNbsps(); duke@1: if (member.tags("deprecated").length > 0) duke@1: writer.printInlineDeprecatedComment(member, member.tags("deprecated")[0]); duke@1: writer.space(); duke@1: writer.summaryRowEnd(); duke@1: writer.trEnd(); duke@1: } duke@1: writer.tableEnd(); duke@1: writer.space(); duke@1: writer.p(); duke@1: } duke@1: } duke@1: duke@1: /** duke@1: * Print use info. duke@1: */ jjg@74: protected void printUseInfo(List mems, String heading) { duke@1: if (mems == null) { duke@1: return; duke@1: } jjg@74: List members = mems; duke@1: if (members.size() > 0) { duke@1: writer.tableIndexSummary(); duke@1: writer.tableUseInfoHeaderStart("#CCCCFF"); duke@1: writer.print(heading); duke@1: writer.tableHeaderEnd(); jjg@74: for (Iterator it = members.iterator(); it.hasNext(); ) { jjg@74: ProgramElementDoc pgmdoc = it.next(); duke@1: ClassDoc cd = pgmdoc.containingClass(); duke@1: duke@1: writer.printSummaryLinkType(this, pgmdoc); duke@1: if (cd != null && !(pgmdoc instanceof ConstructorDoc) duke@1: && !(pgmdoc instanceof ClassDoc)) { duke@1: // Add class context bpatel@182: writer.strong(cd.name() + "."); duke@1: } duke@1: writeSummaryLink( duke@1: pgmdoc instanceof ClassDoc ? duke@1: LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER, duke@1: cd, pgmdoc); duke@1: writer.printSummaryLinkComment(this, pgmdoc); duke@1: } duke@1: writer.tableEnd(); duke@1: writer.space(); duke@1: writer.p(); duke@1: } duke@1: } duke@1: duke@1: protected void navDetailLink(List members) { duke@1: printNavDetailLink(members.size() > 0? true: false); duke@1: } duke@1: duke@1: duke@1: protected void navSummaryLink(List members, duke@1: VisibleMemberMap visibleMemberMap) { duke@1: if (members.size() > 0) { duke@1: printNavSummaryLink(null, true); duke@1: return; duke@1: } else { duke@1: ClassDoc icd = classdoc.superclass(); duke@1: while (icd != null) { duke@1: List inhmembers = visibleMemberMap.getMembersFor(icd); duke@1: if (inhmembers.size() > 0) { duke@1: printNavSummaryLink(icd, true); duke@1: return; duke@1: } duke@1: icd = icd.superclass(); duke@1: } duke@1: } duke@1: printNavSummaryLink(null, false); duke@1: } duke@1: duke@1: protected void serialWarning(SourcePosition pos, String key, String a1, String a2) { duke@1: if (configuration().serialwarn) { duke@1: ConfigurationImpl.getInstance().getDocletSpecificMsg().warning(pos, key, a1, a2); duke@1: } duke@1: } duke@1: duke@1: public ProgramElementDoc[] eligibleMembers(ProgramElementDoc[] members) { duke@1: return nodepr? Util.excludeDeprecatedMembers(members): members; duke@1: } duke@1: duke@1: public ConfigurationImpl configuration() { duke@1: return writer.configuration; duke@1: } duke@1: duke@1: /** duke@1: * {@inheritDoc} duke@1: */ duke@1: public void writeMemberSummary(ClassDoc classDoc, ProgramElementDoc member, duke@1: Tag[] firstSentenceTags, boolean isFirst, boolean isLast) { duke@1: writer.printSummaryLinkType(this, member); duke@1: writeSummaryLink(classDoc, member); duke@1: writer.printSummaryLinkComment(this, member, firstSentenceTags); duke@1: } duke@1: }