1 /*
   2  * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.doclets.internal.toolkit.builders;
  27 
  28 import java.util.*;
  29 
  30 import com.sun.javadoc.*;
  31 import com.sun.tools.doclets.internal.toolkit.*;
  32 import com.sun.tools.doclets.internal.toolkit.util.*;
  33 
  34 /**
  35  * Builds documentation for a method.
  36  *
  37  *  <p><b>This is NOT part of any supported API.
  38  *  If you write code that depends on this, you do so at your own risk.
  39  *  This code and its internal interfaces are subject to change or
  40  *  deletion without notice.</b>
  41  *
  42  * @author Jamie Ho
  43  * @author Bhavesh Patel (Modified)
  44  * @since 1.5
  45  */
  46 public class MethodBuilder extends AbstractMemberBuilder {
  47 
  48     /**
  49      * The index of the current field that is being documented at this point
  50      * in time.
  51      */
  52     private int currentMethodIndex;
  53 
  54     /**
  55      * The class whose methods are being documented.
  56      */
  57     private final ClassDoc classDoc;
  58 
  59     /**
  60      * The visible methods for the given class.
  61      */
  62     private final VisibleMemberMap visibleMemberMap;
  63 
  64     /**
  65      * The writer to output the method documentation.
  66      */
  67     private final MethodWriter writer;
  68 
  69     /**
  70      * The methods being documented.
  71      */
  72     private List<ProgramElementDoc> methods;
  73 
  74 
  75     /**
  76      * Construct a new MethodBuilder.
  77      *
  78      * @param context       the build context.
  79      * @param classDoc the class whoses members are being documented.
  80      * @param writer the doclet specific writer.
  81      */
  82     private MethodBuilder(Context context,
  83             ClassDoc classDoc,
  84             MethodWriter writer) {
  85         super(context);
  86         this.classDoc = classDoc;
  87         this.writer = writer;
  88         visibleMemberMap = new VisibleMemberMap(
  89                 classDoc,
  90                 VisibleMemberMap.METHODS,
  91                 configuration);
  92         methods =
  93                 new ArrayList<>(visibleMemberMap.getLeafClassMembers(configuration));
  94         if (configuration.getMemberComparator() != null) {
  95             Collections.sort(methods, configuration.getMemberComparator());
  96         }
  97     }
  98 
  99     /**
 100      * Construct a new MethodBuilder.
 101      *
 102      * @param context       the build context.
 103      * @param classDoc the class whoses members are being documented.
 104      * @param writer the doclet specific writer.
 105      *
 106      * @return an instance of a MethodBuilder.
 107      */
 108     public static MethodBuilder getInstance(Context context,
 109             ClassDoc classDoc, MethodWriter writer) {
 110         return new MethodBuilder(context, classDoc, writer);
 111     }
 112 
 113     /**
 114      * {@inheritDoc}
 115      */
 116     public String getName() {
 117         return "MethodDetails";
 118     }
 119 
 120     /**
 121      * Returns a list of methods that will be documented for the given class.
 122      * This information can be used for doclet specific documentation
 123      * generation.
 124      *
 125      * @param classDoc the {@link ClassDoc} we want to check.
 126      * @return a list of methods that will be documented.
 127      */
 128     public List<ProgramElementDoc> members(ClassDoc classDoc) {
 129         return visibleMemberMap.getMembersFor(classDoc);
 130     }
 131 
 132     /**
 133      * Returns the visible member map for the methods of this class.
 134      *
 135      * @return the visible member map for the methods of this class.
 136      */
 137     public VisibleMemberMap getVisibleMemberMap() {
 138         return visibleMemberMap;
 139     }
 140 
 141     /**
 142      * {@inheritDoc}
 143      */
 144     public boolean hasMembersToDocument() {
 145         return methods.size() > 0;
 146     }
 147 
 148     /**
 149      * Build the method documentation.
 150      *
 151      * @param node the XML element that specifies which components to document
 152      * @param memberDetailsTree the content tree to which the documentation will be added
 153      */
 154     public void buildMethodDoc(XMLNode node, Content memberDetailsTree) {
 155         if (writer == null) {
 156             return;
 157         }
 158         int size = methods.size();
 159         if (size > 0) {
 160             Content methodDetailsTree = writer.getMethodDetailsTreeHeader(
 161                     classDoc, memberDetailsTree);
 162             for (currentMethodIndex = 0; currentMethodIndex < size;
 163                     currentMethodIndex++) {
 164                 Content methodDocTree = writer.getMethodDocTreeHeader(
 165                         (MethodDoc) methods.get(currentMethodIndex),
 166                         methodDetailsTree);
 167                 buildChildren(node, methodDocTree);
 168                 methodDetailsTree.addContent(writer.getMethodDoc(
 169                         methodDocTree, (currentMethodIndex == size - 1)));
 170             }
 171             memberDetailsTree.addContent(
 172                     writer.getMethodDetails(methodDetailsTree));
 173         }
 174     }
 175 
 176     /**
 177      * Build the signature.
 178      *
 179      * @param node the XML element that specifies which components to document
 180      * @param methodDocTree the content tree to which the documentation will be added
 181      */
 182     public void buildSignature(XMLNode node, Content methodDocTree) {
 183         methodDocTree.addContent(
 184                 writer.getSignature((MethodDoc) methods.get(currentMethodIndex)));
 185     }
 186 
 187     /**
 188      * Build the deprecation information.
 189      *
 190      * @param node the XML element that specifies which components to document
 191      * @param methodDocTree the content tree to which the documentation will be added
 192      */
 193     public void buildDeprecationInfo(XMLNode node, Content methodDocTree) {
 194         writer.addDeprecated(
 195                 (MethodDoc) methods.get(currentMethodIndex), methodDocTree);
 196     }
 197 
 198     /**
 199      * Build the comments for the method.  Do nothing if
 200      * {@link Configuration#nocomment} is set to true.
 201      *
 202      * @param node the XML element that specifies which components to document
 203      * @param methodDocTree the content tree to which the documentation will be added
 204      */
 205     public void buildMethodComments(XMLNode node, Content methodDocTree) {
 206         if (!configuration.nocomment) {
 207             MethodDoc method = (MethodDoc) methods.get(currentMethodIndex);
 208 
 209             if (method.inlineTags().length == 0) {
 210                 DocFinder.Output docs = DocFinder.search(configuration,
 211                         new DocFinder.Input(method));
 212                 method = docs.inlineTags != null && docs.inlineTags.length > 0 ?
 213                     (MethodDoc) docs.holder : method;
 214             }
 215             //NOTE:  When we fix the bug where ClassDoc.interfaceTypes() does
 216             //       not pass all implemented interfaces, holder will be the
 217             //       interface type.  For now, it is really the erasure.
 218             writer.addComments(method.containingClass(), method, methodDocTree);
 219         }
 220     }
 221 
 222     /**
 223      * Build the tag information.
 224      *
 225      * @param node the XML element that specifies which components to document
 226      * @param methodDocTree the content tree to which the documentation will be added
 227      */
 228     public void buildTagInfo(XMLNode node, Content methodDocTree) {
 229         writer.addTags((MethodDoc) methods.get(currentMethodIndex),
 230                 methodDocTree);
 231     }
 232 
 233     /**
 234      * Return the method writer for this builder.
 235      *
 236      * @return the method writer for this builder.
 237      */
 238     public MethodWriter getWriter() {
 239         return writer;
 240     }
 241 }