001    /*
002     * Copyright 2003-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.internal.toolkit.builders;
027    
028    import com.sun.tools.doclets.internal.toolkit.util.*;
029    import com.sun.tools.doclets.internal.toolkit.*;
030    import com.sun.javadoc.*;
031    import java.util.*;
032    import java.lang.reflect.*;
033    /**
034     * Builds documentation for a method.
035     *
036     * This code is not part of an API.
037     * It is implementation that is subject to change.
038     * Do not use it as an API
039     *
040     * @author Jamie Ho
041     * @since 1.5
042     */
043    public class MethodBuilder extends AbstractMemberBuilder {
044    
045            /**
046             * The index of the current field that is being documented at this point
047             * in time.
048             */
049            private int currentMethodIndex;
050    
051            /**
052             * The class whose methods are being documented.
053             */
054            private ClassDoc classDoc;
055    
056            /**
057             * The visible methods for the given class.
058             */
059            private VisibleMemberMap visibleMemberMap;
060    
061            /**
062             * The writer to output the method documentation.
063             */
064            private MethodWriter writer;
065    
066            /**
067             * The methods being documented.
068             */
069            private List<ProgramElementDoc> methods;
070    
071            private MethodBuilder(Configuration configuration) {
072                    super(configuration);
073            }
074    
075            /**
076             * Construct a new MethodBuilder.
077             *
078             * @param configuration the current configuration of the doclet.
079             * @param classDoc the class whoses members are being documented.
080             * @param writer the doclet specific writer.
081             *
082             * @return an instance of a MethodBuilder.
083             */
084            public static MethodBuilder getInstance(
085                    Configuration configuration,
086                    ClassDoc classDoc,
087                    MethodWriter writer) {
088                    MethodBuilder builder = new MethodBuilder(configuration);
089                    builder.classDoc = classDoc;
090                    builder.writer = writer;
091                    builder.visibleMemberMap =
092                            new VisibleMemberMap(
093                                    classDoc,
094                                    VisibleMemberMap.METHODS,
095                                    configuration.nodeprecated);
096                    builder.methods =
097                            new ArrayList<ProgramElementDoc>(builder.visibleMemberMap.getLeafClassMembers(
098                    configuration));
099                    if (configuration.getMemberComparator() != null) {
100                            Collections.sort(
101                                    builder.methods,
102                                    configuration.getMemberComparator());
103                    }
104                    return builder;
105            }
106    
107            /**
108             * {@inheritDoc}
109             */
110            public String getName() {
111                    return "MethodDetails";
112            }
113    
114            /**
115             * {@inheritDoc}
116             */
117            public void invokeMethod(
118                    String methodName,
119                    Class<?>[] paramClasses,
120                    Object[] params)
121                    throws Exception {
122                    if (DEBUG) {
123                            configuration.root.printError(
124                                    "DEBUG: " + this.getClass().getName() + "." + methodName);
125                    }
126                    Method method = this.getClass().getMethod(methodName, paramClasses);
127                    method.invoke(this, params);
128            }
129    
130            /**
131             * Returns a list of methods that will be documented for the given class.
132             * This information can be used for doclet specific documentation
133             * generation.
134             *
135             * @param classDoc the {@link ClassDoc} we want to check.
136             * @return a list of methods that will be documented.
137             */
138            public List<ProgramElementDoc> members(ClassDoc classDoc) {
139                    return visibleMemberMap.getMembersFor(classDoc);
140            }
141    
142            /**
143             * Returns the visible member map for the methods of this class.
144             *
145             * @return the visible member map for the methods of this class.
146             */
147            public VisibleMemberMap getVisibleMemberMap() {
148                    return visibleMemberMap;
149            }
150    
151            /**
152             * {@inheritDoc}
153             */
154            public boolean hasMembersToDocument() {
155                    return methods.size() > 0;
156            }
157    
158            /**
159             * Build the method documentation.
160             */
161            public void buildMethodDoc(List<?> elements) {
162                    if (writer == null) {
163                            return;
164                    }
165                    for (currentMethodIndex = 0;
166                            currentMethodIndex < methods.size();
167                            currentMethodIndex++) {
168                            build(elements);
169                    }
170            }
171    
172            /**
173             * Build the overall header.
174             */
175            public void buildHeader() {
176                    writer.writeHeader(
177                            classDoc,
178                            configuration.getText("doclet.Method_Detail"));
179            }
180    
181            /**
182             * Build the header for the individual method.
183             */
184            public void buildMethodHeader() {
185                    writer.writeMethodHeader(
186                            (MethodDoc) methods.get(currentMethodIndex),
187                            currentMethodIndex == 0);
188            }
189    
190            /**
191             * Build the signature.
192             */
193            public void buildSignature() {
194                    writer.writeSignature((MethodDoc) methods.get(currentMethodIndex));
195            }
196    
197            /**
198             * Build the deprecation information.
199             */
200            public void buildDeprecationInfo() {
201                    writer.writeDeprecated((MethodDoc) methods.get(currentMethodIndex));
202            }
203    
204            /**
205             * Build the comments for the method.  Do nothing if
206             * {@link Configuration#nocomment} is set to true.  If this method
207             */
208            public void buildMethodComments() {
209                    if (!configuration.nocomment) {
210                MethodDoc method = (MethodDoc) methods.get(currentMethodIndex);
211    
212                if (method.inlineTags().length == 0) {
213                    DocFinder.Output docs = DocFinder.search(
214                        new DocFinder.Input(method));
215                    method = docs.inlineTags != null && docs.inlineTags.length > 0 ?
216                        (MethodDoc) docs.holder : method;
217    
218                }
219                //NOTE:  When we fix the bug where ClassDoc.interfaceTypes() does
220                //       not pass all implemented interfaces, holder will be the
221                //       interface type.  For now, it is really the erasure.
222                writer.writeComments(method.containingClass(), method);
223                    }
224            }
225    
226    
227    
228            /**
229             * Build the tag information.
230             */
231            public void buildTagInfo() {
232                    writer.writeTags((MethodDoc) methods.get(currentMethodIndex));
233            }
234    
235            /**
236             * Build the footer of the method.
237             */
238            public void buildMethodFooter() {
239                    writer.writeMethodFooter();
240            }
241    
242            /**
243             * Build the overall footer.
244             */
245            public void buildFooter() {
246                    writer.writeFooter(classDoc);
247            }
248    
249            /**
250             * Return the method writer for this builder.
251             *
252             * @return the method writer for this builder.
253             */
254            public MethodWriter getWriter() {
255                    return writer;
256            }
257    }