001    /*
002     * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.doclets.formats.html;
027    
028    import com.sun.tools.doclets.internal.toolkit.util.*;
029    import com.sun.tools.doclets.internal.toolkit.taglets.*;
030    
031    import com.sun.javadoc.*;
032    import java.util.*;
033    import java.lang.reflect.Modifier;
034    
035    /**
036     * The base class for member writers.
037     *
038     * @author Robert Field
039     * @author Atul M Dambalkar
040     * @author Jamie Ho (Re-write)
041     */
042    public abstract class AbstractMemberWriter {
043    
044        protected boolean printedSummaryHeader = false;
045        protected final SubWriterHolderWriter writer;
046        protected final ClassDoc classdoc;
047        public final boolean nodepr;
048    
049        public AbstractMemberWriter(SubWriterHolderWriter writer,
050                                 ClassDoc classdoc) {
051            this.writer = writer;
052            this.nodepr = configuration().nodeprecated;
053            this.classdoc = classdoc;
054        }
055    
056        public AbstractMemberWriter(SubWriterHolderWriter writer) {
057            this(writer, null);
058        }
059    
060        /*** abstracts ***/
061    
062        public abstract void printSummaryLabel(ClassDoc cd);
063    
064        public abstract void printInheritedSummaryLabel(ClassDoc cd);
065    
066        public abstract void printSummaryAnchor(ClassDoc cd);
067    
068        public abstract void printInheritedSummaryAnchor(ClassDoc cd);
069    
070        protected abstract void printSummaryType(ProgramElementDoc member);
071    
072        protected void writeSummaryLink(ClassDoc cd, ProgramElementDoc member) {
073            writeSummaryLink(LinkInfoImpl.CONTEXT_MEMBER, cd, member);
074        }
075    
076        protected abstract void writeSummaryLink(int context,
077                                                 ClassDoc cd,
078                                                 ProgramElementDoc member);
079    
080        protected abstract void writeInheritedSummaryLink(ClassDoc cd,
081                                                         ProgramElementDoc member);
082    
083        protected abstract void writeDeprecatedLink(ProgramElementDoc member);
084    
085        protected abstract void printNavSummaryLink(ClassDoc cd, boolean link);
086    
087        protected abstract void printNavDetailLink(boolean link);
088    
089        /***  ***/
090    
091        protected void print(String str) {
092            writer.print(str);
093            writer.displayLength += str.length();
094        }
095    
096        protected void print(char ch) {
097            writer.print(ch);
098            writer.displayLength++;
099        }
100    
101        protected void strong(String str) {
102            writer.strong(str);
103            writer.displayLength += str.length();
104        }
105    
106        /**
107         * Return a string describing the access modifier flags.
108         * Don't include native or synchronized.
109         *
110         * The modifier names are returned in canonical order, as
111         * specified by <em>The Java Language Specification</em>.
112         */
113        protected String modifierString(MemberDoc member) {
114            int ms = member.modifierSpecifier();
115            int no = Modifier.NATIVE | Modifier.SYNCHRONIZED;
116        return Modifier.toString(ms & ~no);
117        }
118    
119        protected String typeString(MemberDoc member) {
120            String type = "";
121            if (member instanceof MethodDoc) {
122                type = ((MethodDoc)member).returnType().toString();
123            } else if (member instanceof FieldDoc) {
124                type = ((FieldDoc)member).type().toString();
125            }
126            return type;
127        }
128    
129        protected void printModifiers(MemberDoc member) {
130            String mod = modifierString(member);
131            // According to JLS, we should not be showing public modifier for
132            // interface methods.
133            if ((member.isField() || member.isMethod()) &&
134                writer instanceof ClassWriterImpl &&
135                 ((ClassWriterImpl) writer).getClassDoc().isInterface()) {
136                mod = Util.replaceText(mod, "public", "").trim();
137            }
138            if(mod.length() > 0) {
139                print(mod);
140                print(' ');
141            }
142        }
143    
144        protected String makeSpace(int len) {
145            if (len <= 0) {
146                return "";
147            }
148            StringBuffer sb = new StringBuffer(len);
149            for(int i = 0; i < len; i++) {
150                sb.append(' ');
151        }
152            return sb.toString();
153        }
154    
155        /**
156         * Print 'static' if static and type link.
157         */
158        protected void printStaticAndType(boolean isStatic, Type type) {
159            writer.printTypeSummaryHeader();
160            if (isStatic) {
161                print("static");
162            }
163            writer.space();
164            if (type != null) {
165                writer.printLink(new LinkInfoImpl(LinkInfoImpl.CONTEXT_MEMBER,
166                    type));
167            }
168            writer.printTypeSummaryFooter();
169        }
170    
171        /**
172         * Print the modifier and type for the member in the member summary.
173         *
174         * @param member the member to print the type for.
175         * @param type   the type to print.
176         */
177        protected void printModifierAndType(ProgramElementDoc member, Type type) {
178            writer.printTypeSummaryHeader();
179            printModifier(member);
180            if (type == null) {
181                writer.space();
182                if (member.isClass()) {
183                    print("class");
184                } else {
185                    print("interface");
186                }
187            } else {
188                if (member instanceof ExecutableMemberDoc &&
189                        ((ExecutableMemberDoc) member).typeParameters().length > 0) {
190                    //Code to avoid ugly wrapping in member summary table.
191                    writer.table(0,0,0);
192                    writer.trAlignVAlign("right", "");
193                    writer.tdNowrap();
194                    writer.font("-1");
195                    writer.code();
196                    int displayLength = ((AbstractExecutableMemberWriter) this).
197                    writeTypeParameters((ExecutableMemberDoc) member);
198                    if (displayLength > 10) {
199                        writer.br();
200                    }
201                    writer.printLink(new LinkInfoImpl(
202                        LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type));
203                    writer.codeEnd();
204                    writer.fontEnd();
205                    writer.tdEnd();
206                    writer.trEnd();
207                    writer.tableEnd();
208                } else {
209                    writer.space();
210                    writer.printLink(new LinkInfoImpl(
211                        LinkInfoImpl.CONTEXT_SUMMARY_RETURN_TYPE, type));
212                }
213    
214            }
215            writer.printTypeSummaryFooter();
216        }
217    
218        private void printModifier(ProgramElementDoc member) {
219            if (member.isProtected()) {
220                print("protected ");
221            } else if (member.isPrivate()) {
222                print("private ");
223            } else if (!member.isPublic()) { // Package private
224                writer.printText("doclet.Package_private");
225                print(" ");
226            }
227            if (member.isMethod() && ((MethodDoc)member).isAbstract()) {
228                print("abstract ");
229            }
230            if (member.isStatic()) {
231                print("static");
232            }
233        }
234    
235        protected void printComment(ProgramElementDoc member) {
236            if (member.inlineTags().length > 0) {
237                writer.dd();
238                writer.printInlineComment(member);
239            }
240        }
241    
242        protected String name(ProgramElementDoc member) {
243            return member.name();
244        }
245    
246        protected void printHead(MemberDoc member) {
247            writer.h3();
248            writer.print(member.name());
249            writer.h3End();
250        }
251    
252        protected void printFullComment(ProgramElementDoc member) {
253            if(configuration().nocomment){
254                return;
255            }
256            writer.dl();
257            print(((TagletOutputImpl)
258                (new DeprecatedTaglet()).getTagletOutput(member,
259                writer.getTagletWriterInstance(false))).toString());
260            printCommentAndTags(member);
261            writer.dlEnd();
262        }
263    
264        protected void printCommentAndTags(ProgramElementDoc member) {
265            printComment(member);
266            writer.printTags(member);
267        }
268    
269        /**
270         * Forward to containing writer
271         */
272        public void printSummaryHeader(ClassDoc cd) {
273            printedSummaryHeader = true;
274            writer.printSummaryHeader(this, cd);
275        }
276    
277        /**
278         * Forward to containing writer
279         */
280        public void printInheritedSummaryHeader(ClassDoc cd) {
281            writer.printInheritedSummaryHeader(this, cd);
282        }
283    
284        /**
285         * Forward to containing writer
286         */
287        public void printInheritedSummaryFooter(ClassDoc cd) {
288            writer.printInheritedSummaryFooter(this, cd);
289        }
290    
291        /**
292         * Forward to containing writer
293         */
294        public void printSummaryFooter(ClassDoc cd) {
295            writer.printSummaryFooter(this, cd);
296        }
297    
298       /**
299        * Return true if the given <code>ProgramElement</code> is inherited
300        * by the class that is being documented.
301        *
302        * @param ped The <code>ProgramElement</code> being checked.
303        * return true if the <code>ProgramElement</code> is being inherited and
304        * false otherwise.
305        */
306        protected boolean isInherited(ProgramElementDoc ped){
307            if(ped.isPrivate() || (ped.isPackagePrivate() &&
308                ! ped.containingPackage().equals(classdoc.containingPackage()))){
309                return false;
310            }
311            return true;
312        }
313    
314    
315        /**
316         * Generate the code for listing the deprecated APIs. Create the table
317         * format for listing the API. Call methods from the sub-class to complete
318         * the generation.
319         */
320        protected void printDeprecatedAPI(List<Doc> deprmembers, String headingKey) {
321            if (deprmembers.size() > 0) {
322                writer.tableIndexSummary();
323                writer.tableHeaderStart("#CCCCFF");
324                writer.strongText(headingKey);
325                writer.tableHeaderEnd();
326                for (int i = 0; i < deprmembers.size(); i++) {
327                    ProgramElementDoc member =(ProgramElementDoc)deprmembers.get(i);
328                    writer.trBgcolorStyle("white", "TableRowColor");
329                    writer.summaryRow(0);
330                    writeDeprecatedLink(member);
331                    writer.br();
332                    writer.printNbsps();
333                    if (member.tags("deprecated").length > 0)
334                        writer.printInlineDeprecatedComment(member, member.tags("deprecated")[0]);
335                    writer.space();
336                    writer.summaryRowEnd();
337                    writer.trEnd();
338                }
339                writer.tableEnd();
340                writer.space();
341                writer.p();
342            }
343        }
344    
345        /**
346         * Print use info.
347         */
348        protected void printUseInfo(List<? extends ProgramElementDoc> mems, String heading) {
349            if (mems == null) {
350                return;
351            }
352            List<? extends ProgramElementDoc> members = mems;
353            if (members.size() > 0) {
354                writer.tableIndexSummary();
355                writer.tableUseInfoHeaderStart("#CCCCFF");
356                writer.print(heading);
357                writer.tableHeaderEnd();
358                for (Iterator<? extends ProgramElementDoc> it = members.iterator(); it.hasNext(); ) {
359                    ProgramElementDoc pgmdoc = it.next();
360                    ClassDoc cd = pgmdoc.containingClass();
361    
362                    writer.printSummaryLinkType(this, pgmdoc);
363                    if (cd != null && !(pgmdoc instanceof ConstructorDoc)
364                                   && !(pgmdoc instanceof ClassDoc)) {
365                        // Add class context
366                        writer.strong(cd.name() + ".");
367                    }
368                    writeSummaryLink(
369                        pgmdoc instanceof ClassDoc ?
370                            LinkInfoImpl.CONTEXT_CLASS_USE : LinkInfoImpl.CONTEXT_MEMBER,
371                        cd, pgmdoc);
372                    writer.printSummaryLinkComment(this, pgmdoc);
373                }
374                writer.tableEnd();
375                writer.space();
376                writer.p();
377            }
378        }
379    
380        protected void navDetailLink(List<?> members) {
381                printNavDetailLink(members.size() > 0? true: false);
382        }
383    
384    
385        protected void navSummaryLink(List<?> members,
386                VisibleMemberMap visibleMemberMap) {
387            if (members.size() > 0) {
388                printNavSummaryLink(null, true);
389                return;
390            } else {
391                ClassDoc icd = classdoc.superclass();
392                while (icd != null) {
393                    List<?> inhmembers = visibleMemberMap.getMembersFor(icd);
394                    if (inhmembers.size() > 0) {
395                        printNavSummaryLink(icd, true);
396                        return;
397                    }
398                    icd = icd.superclass();
399                }
400            }
401            printNavSummaryLink(null, false);
402        }
403    
404        protected void serialWarning(SourcePosition pos, String key, String a1, String a2) {
405            if (configuration().serialwarn) {
406                ConfigurationImpl.getInstance().getDocletSpecificMsg().warning(pos, key, a1, a2);
407            }
408        }
409    
410        public ProgramElementDoc[] eligibleMembers(ProgramElementDoc[] members) {
411            return nodepr? Util.excludeDeprecatedMembers(members): members;
412        }
413    
414        public ConfigurationImpl configuration() {
415            return writer.configuration;
416        }
417    
418        /**
419         * {@inheritDoc}
420         */
421        public void writeMemberSummary(ClassDoc classDoc, ProgramElementDoc member,
422            Tag[] firstSentenceTags, boolean isFirst, boolean isLast) {
423            writer.printSummaryLinkType(this, member);
424            writeSummaryLink(classDoc, member);
425            writer.printSummaryLinkComment(this, member, firstSentenceTags);
426        }
427    }