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 extends ProgramElementDoc> mems, String heading) {
duke@1: if (mems == null) {
duke@1: return;
duke@1: }
jjg@74: List extends ProgramElementDoc> 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 extends ProgramElementDoc> 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: }