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    /**
035     * Builds the member summary.
036     *
037     * This code is not part of an API.
038     * It is implementation that is subject to change.
039     * Do not use it as an API
040     *
041     * @author Jamie Ho
042     * @since 1.5
043     */
044    public class MemberSummaryBuilder extends AbstractMemberBuilder {
045    
046            /**
047             * The XML root for this builder.
048             */
049            public static final String NAME = "MemberSummary";
050    
051            /**
052             * The visible members for the given class.
053             */
054            private VisibleMemberMap[] visibleMemberMaps;
055    
056            /**
057             * The member summary writers for the given class.
058             */
059            private MemberSummaryWriter[] memberSummaryWriters;
060    
061            /**
062             * The type being documented.
063             */
064            private ClassDoc classDoc;
065    
066            private MemberSummaryBuilder(Configuration configuration) {
067                    super(configuration);
068            }
069    
070            /**
071             * Construct a new MemberSummaryBuilder.
072             *
073             * @param classWriter   the writer for the class whose members are being
074             *                      summarized.
075             * @param configuration the current configuration of the doclet.
076             */
077            public static MemberSummaryBuilder getInstance(
078                    ClassWriter classWriter, Configuration configuration)
079            throws Exception {
080                    MemberSummaryBuilder builder = new MemberSummaryBuilder(configuration);
081                    builder.classDoc = classWriter.getClassDoc();
082                    builder.init(classWriter);
083                    return builder;
084            }
085    
086        /**
087         * Construct a new MemberSummaryBuilder.
088         *
089         * @param annotationTypeWriter the writer for the class whose members are
090         *                             being summarized.
091         * @param configuration the current configuration of the doclet.
092         */
093        public static MemberSummaryBuilder getInstance(
094            AnnotationTypeWriter annotationTypeWriter, Configuration configuration)
095        throws Exception {
096            MemberSummaryBuilder builder = new MemberSummaryBuilder(configuration);
097            builder.classDoc = annotationTypeWriter.getAnnotationTypeDoc();
098            builder.init(annotationTypeWriter);
099            return builder;
100        }
101    
102        private void init(Object writer) throws Exception {
103            visibleMemberMaps =
104                new VisibleMemberMap[VisibleMemberMap.NUM_MEMBER_TYPES];
105            for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
106                visibleMemberMaps[i] =
107                    new VisibleMemberMap(
108                        classDoc,
109                        i,
110                        configuration.nodeprecated);
111            }
112            memberSummaryWriters =
113                new MemberSummaryWriter[VisibleMemberMap.NUM_MEMBER_TYPES];
114            for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
115                if (classDoc.isAnnotationType()) {
116                    memberSummaryWriters[i] =
117                        visibleMemberMaps[i].noVisibleMembers()?
118                            null :
119                            configuration.getWriterFactory().getMemberSummaryWriter(
120                                (AnnotationTypeWriter) writer, i);
121                } else {
122                    memberSummaryWriters[i] =
123                        visibleMemberMaps[i].noVisibleMembers()?
124                            null :
125                            configuration.getWriterFactory().getMemberSummaryWriter(
126                                (ClassWriter) writer, i);
127                }
128            }
129    
130        }
131    
132            /**
133             * {@inheritDoc}
134             */
135            public String getName() {
136                    return NAME;
137            }
138    
139            /**
140             * Return the specified visible member map.
141             *
142             * @param type the type of visible member map to return.
143             * @return the specified visible member map.
144             * @throws ArrayIndexOutOfBoundsException when the type is invalid.
145             * @see VisibleMemberMap
146             */
147            public VisibleMemberMap getVisibleMemberMap(int type) {
148                    return visibleMemberMaps[type];
149            }
150    
151            /**
152             * Return the specified member summary writer.
153             *
154             * @param type the type of member summary writer to return.
155             * @return the specified member summary writer.
156             * @throws ArrayIndexOutOfBoundsException when the type is invalid.
157             * @see VisibleMemberMap
158             */
159            public MemberSummaryWriter getMemberSummaryWriter(int type) {
160                    return memberSummaryWriters[type];
161            }
162    
163            /**
164             * Returns a list of methods that will be documented for the given class.
165             * This information can be used for doclet specific documentation
166             * generation.
167             *
168             * @param classDoc the {@link ClassDoc} we want to check.
169             * @param type the type of members to return.
170             * @return a list of methods that will be documented.
171             * @see VisibleMemberMap
172             */
173            public List<ProgramElementDoc> members(int type) {
174                    return visibleMemberMaps[type].getLeafClassMembers(configuration);
175            }
176    
177            /**
178             * {@inheritDoc}
179             */
180            public void invokeMethod(
181                    String methodName,
182                    Class<?>[] paramClasses,
183                    Object[] params)
184                    throws Exception {
185                    if (DEBUG) {
186                            configuration.root.printError(
187                                    "DEBUG: " + this.getClass().getName() + "." + methodName);
188                    }
189                    Method method = this.getClass().getMethod(methodName, paramClasses);
190                    method.invoke(this, params);
191            }
192    
193            /**
194             * Return true it there are any members to summarize.
195             *
196             * @return true if there are any members to summarize.
197             */
198            public boolean hasMembersToDocument() {
199            if (classDoc instanceof AnnotationTypeDoc) {
200                return ((AnnotationTypeDoc) classDoc).elements().length > 0;
201            }
202                    for (int i = 0; i < VisibleMemberMap.NUM_MEMBER_TYPES; i++) {
203                            VisibleMemberMap members = visibleMemberMaps[i];
204                            if (!members.noVisibleMembers()) {
205                                    return true;
206                            }
207                    }
208                    return false;
209            }
210    
211            /**
212             * Build the summary for the enum constants.
213             */
214            public void buildEnumConstantsSummary() {
215                    buildSummary(
216                            memberSummaryWriters[VisibleMemberMap.ENUM_CONSTANTS],
217                            visibleMemberMaps[VisibleMemberMap.ENUM_CONSTANTS]);
218            }
219    
220        /**
221         * Build the summary for the optional members.
222         */
223        public void buildAnnotationTypeOptionalMemberSummary() {
224            buildSummary(
225                memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL],
226                    visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL]);
227        }
228    
229        /**
230         * Build the summary for the optional members.
231         */
232        public void buildAnnotationTypeRequiredMemberSummary() {
233            buildSummary(
234                memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED],
235                    visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED]);
236        }
237    
238            /**
239             * Build the summary for the fields.
240             */
241            public void buildFieldsSummary() {
242                    buildSummary(
243                            memberSummaryWriters[VisibleMemberMap.FIELDS],
244                            visibleMemberMaps[VisibleMemberMap.FIELDS]);
245            }
246    
247            /**
248             * Build the inherited summary for the fields.
249             */
250            public void buildFieldsInheritedSummary() {
251                    buildInheritedSummary(
252                            memberSummaryWriters[VisibleMemberMap.FIELDS],
253                            visibleMemberMaps[VisibleMemberMap.FIELDS]);
254            }
255    
256            /**
257             * Build the summary for the nested classes.
258             */
259            public void buildNestedClassesSummary() {
260                    buildSummary(
261                            memberSummaryWriters[VisibleMemberMap.INNERCLASSES],
262                            visibleMemberMaps[VisibleMemberMap.INNERCLASSES]);
263            }
264    
265            /**
266             * Build the inherited summary for the nested classes.
267             */
268            public void buildNestedClassesInheritedSummary() {
269                    buildInheritedSummary(
270                            memberSummaryWriters[VisibleMemberMap.INNERCLASSES],
271                            visibleMemberMaps[VisibleMemberMap.INNERCLASSES]);
272            }
273    
274            /**
275             * Build the method summary.
276             */
277            public void buildMethodsSummary() {
278                    buildSummary(
279                            memberSummaryWriters[VisibleMemberMap.METHODS],
280                            visibleMemberMaps[VisibleMemberMap.METHODS]);
281            }
282    
283            /**
284             * Build the inherited method summary.
285             */
286            public void buildMethodsInheritedSummary() {
287                    buildInheritedSummary(
288                            memberSummaryWriters[VisibleMemberMap.METHODS],
289                            visibleMemberMaps[VisibleMemberMap.METHODS]);
290            }
291    
292            /**
293             * Build the constructor summary.
294             */
295            public void buildConstructorsSummary() {
296                    buildSummary(
297                            memberSummaryWriters[VisibleMemberMap.CONSTRUCTORS],
298                            visibleMemberMaps[VisibleMemberMap.CONSTRUCTORS]);
299            }
300    
301            /**
302             * Build the member summary for the given members.
303             *
304             * @param writer           the summary writer to write the output.
305             * @param visibleMemberMap the given members to summarize.
306             */
307            private void buildSummary(MemberSummaryWriter writer,
308                VisibleMemberMap visibleMemberMap) {
309            List<ProgramElementDoc> members = new ArrayList<ProgramElementDoc>(visibleMemberMap.getLeafClassMembers(
310                configuration));
311            if (members.size() > 0) {
312                Collections.sort(members);
313                writer.writeMemberSummaryHeader(classDoc);
314                for (int i = 0; i < members.size(); i++) {
315                    ProgramElementDoc member = members.get(i);
316                    Tag[] firstSentenceTags = member.firstSentenceTags();
317                    if (member instanceof MethodDoc && firstSentenceTags.length == 0) {
318                        //Inherit comments from overriden or implemented method if
319                        //necessary.
320                        DocFinder.Output inheritedDoc =
321                            DocFinder.search(new DocFinder.Input((MethodDoc) member));
322                        if (inheritedDoc.holder != null &&
323                                inheritedDoc.holder.firstSentenceTags().length > 0) {
324                            firstSentenceTags = inheritedDoc.holder.firstSentenceTags();
325                        }
326                    }
327                    writer.writeMemberSummary(classDoc, member, firstSentenceTags,
328                        i == 0, i == members.size() - 1);
329                }
330                writer.writeMemberSummaryFooter(classDoc);
331            }
332            }
333    
334        /**
335         * Build the inherited member summary for the given methods.
336         *
337         * @param writer           the writer for this member summary.
338         * @param visibleMemberMap the map for the members to document.
339         */
340            private void buildInheritedSummary(MemberSummaryWriter writer,
341                VisibleMemberMap visibleMemberMap) {
342            for (Iterator<ClassDoc> iter = visibleMemberMap.getVisibleClassesList().iterator();
343                    iter.hasNext();) {
344                ClassDoc inhclass = iter.next();
345                if (! (inhclass.isPublic() ||
346                    Util.isLinkable(inhclass, configuration))) {
347                    continue;
348                }
349                if (inhclass == classDoc) {
350                    continue;
351                }
352                List<ProgramElementDoc> inhmembers = visibleMemberMap.getMembersFor(inhclass);
353                if (inhmembers.size() > 0) {
354                    Collections.sort(inhmembers);
355                    writer.writeInheritedMemberSummaryHeader(inhclass);
356                    for (int j = 0; j < inhmembers.size(); ++j) {
357                        writer.writeInheritedMemberSummary(
358                            inhclass.isPackagePrivate() &&
359                                ! Util.isLinkable(inhclass, configuration) ?
360                                classDoc : inhclass,
361                            inhmembers.get(j),
362                            j == 0,
363                            j == inhmembers.size() - 1);
364                    }
365                    writer.writeInheritedMemberSummaryFooter(inhclass);
366                }
367            }
368        }
369    }