1 /*
   2  * Copyright (c) 1997, 2017, 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 jdk.javadoc.internal.doclets.formats.html;
  27 
  28 import jdk.javadoc.internal.doclets.formats.html.markup.Table;
  29 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader;
  30 
  31 import java.util.*;
  32 
  33 import javax.lang.model.element.Element;
  34 import javax.lang.model.element.ExecutableElement;
  35 import javax.lang.model.element.TypeElement;
  36 
  37 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
  38 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  39 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
  40 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  41 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  42 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
  43 import jdk.javadoc.internal.doclets.toolkit.Content;
  44 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
  45 import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
  46 
  47 
  48 /**
  49  * Writes constructor documentation.
  50  *
  51  *  <p><b>This is NOT part of any supported API.
  52  *  If you write code that depends on this, you do so at your own risk.
  53  *  This code and its internal interfaces are subject to change or
  54  *  deletion without notice.</b>
  55  *
  56  * @author Robert Field
  57  * @author Atul M Dambalkar
  58  * @author Bhavesh Patel (Modified)
  59  */
  60 public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
  61     implements ConstructorWriter, MemberSummaryWriter {
  62 
  63     private boolean foundNonPubConstructor = false;
  64 
  65     /**
  66      * Construct a new ConstructorWriterImpl.
  67      *
  68      * @param writer The writer for the class that the constructors belong to.
  69      * @param typeElement the class being documented.
  70      */
  71     public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
  72         super(writer, typeElement);
  73 
  74         VisibleMemberMap visibleMemberMap = configuration.getVisibleMemberMap(
  75                 typeElement,
  76                 VisibleMemberMap.Kind.CONSTRUCTORS);
  77         List<Element> constructors = visibleMemberMap.getMembers(typeElement);
  78         for (Element constructor : constructors) {
  79             if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
  80                 setFoundNonPubConstructor(true);
  81             }
  82         }
  83     }
  84 
  85     /**
  86      * Construct a new ConstructorWriterImpl.
  87      *
  88      * @param writer The writer for the class that the constructors belong to.
  89      */
  90     public ConstructorWriterImpl(SubWriterHolderWriter writer) {
  91         super(writer);
  92     }
  93 
  94     /**
  95      * {@inheritDoc}
  96      */
  97     @Override
  98     public Content getMemberSummaryHeader(TypeElement typeElement,
  99             Content memberSummaryTree) {
 100         memberSummaryTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_SUMMARY);
 101         Content memberTree = writer.getMemberTreeHeader();
 102         writer.addSummaryHeader(this, typeElement, memberTree);
 103         return memberTree;
 104     }
 105 
 106     /**
 107      * {@inheritDoc}
 108      */
 109     @Override
 110     public void addMemberTree(Content memberSummaryTree, Content memberTree) {
 111         writer.addMemberTree(memberSummaryTree, memberTree);
 112     }
 113 
 114     /**
 115      * {@inheritDoc}
 116      */
 117     @Override
 118     public Content getConstructorDetailsTreeHeader(TypeElement typeElement,
 119             Content memberDetailsTree) {
 120         memberDetailsTree.addContent(HtmlConstants.START_OF_CONSTRUCTOR_DETAILS);
 121         Content constructorDetailsTree = writer.getMemberTreeHeader();
 122         constructorDetailsTree.addContent(writer.getMarkerAnchor(
 123                 SectionName.CONSTRUCTOR_DETAIL));
 124         Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING,
 125                 contents.constructorDetailsLabel);
 126         constructorDetailsTree.addContent(heading);
 127         return constructorDetailsTree;
 128     }
 129 
 130     /**
 131      * {@inheritDoc}
 132      */
 133     @Override
 134     public Content getConstructorDocTreeHeader(ExecutableElement constructor,
 135             Content constructorDetailsTree) {
 136         String erasureAnchor;
 137         if ((erasureAnchor = getErasureAnchor(constructor)) != null) {
 138             constructorDetailsTree.addContent(writer.getMarkerAnchor((erasureAnchor)));
 139         }
 140         constructorDetailsTree.addContent(
 141                 writer.getMarkerAnchor(writer.getAnchor(constructor)));
 142         Content constructorDocTree = writer.getMemberTreeHeader();
 143         Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING);
 144         heading.addContent(name(constructor));
 145         constructorDocTree.addContent(heading);
 146         return constructorDocTree;
 147     }
 148 
 149     /**
 150      * {@inheritDoc}
 151      */
 152     @Override
 153     public Content getSignature(ExecutableElement constructor) {
 154         Content pre = new HtmlTree(HtmlTag.PRE);
 155         writer.addAnnotationInfo(constructor, pre);
 156         int annotationLength = pre.charCount();
 157         addModifiers(constructor, pre);
 158         if (configuration.linksource) {
 159             Content constructorName = new StringContent(name(constructor));
 160             writer.addSrcLink(constructor, constructorName, pre);
 161         } else {
 162             addName(name(constructor), pre);
 163         }
 164         int indent = pre.charCount() - annotationLength;
 165         addParameters(constructor, pre, indent);
 166         addExceptions(constructor, pre, indent);
 167         return pre;
 168     }
 169 
 170     /**
 171      * {@inheritDoc}
 172      */
 173     @Override
 174     public void addDeprecated(ExecutableElement constructor, Content constructorDocTree) {
 175         addDeprecatedInfo(constructor, constructorDocTree);
 176     }
 177 
 178     /**
 179      * {@inheritDoc}
 180      */
 181     @Override
 182     public void addComments(ExecutableElement constructor, Content constructorDocTree) {
 183         addComment(constructor, constructorDocTree);
 184     }
 185 
 186     /**
 187      * {@inheritDoc}
 188      */
 189     @Override
 190     public void addTags(ExecutableElement constructor, Content constructorDocTree) {
 191         writer.addTagsInfo(constructor, constructorDocTree);
 192     }
 193 
 194     /**
 195      * {@inheritDoc}
 196      */
 197     @Override
 198     public Content getConstructorDetails(Content constructorDetailsTree) {
 199         if (configuration.allowTag(HtmlTag.SECTION)) {
 200             HtmlTree htmlTree = HtmlTree.SECTION(getMemberTree(constructorDetailsTree));
 201             return htmlTree;
 202         }
 203         return getMemberTree(constructorDetailsTree);
 204     }
 205 
 206     /**
 207      * {@inheritDoc}
 208      */
 209     @Override
 210     public Content getConstructorDoc(Content constructorDocTree,
 211             boolean isLastContent) {
 212         return getMemberTree(constructorDocTree, isLastContent);
 213     }
 214 
 215     /**
 216      * Let the writer know whether a non public constructor was found.
 217      *
 218      * @param foundNonPubConstructor true if we found a non public constructor.
 219      */
 220     @Override
 221     public void setFoundNonPubConstructor(boolean foundNonPubConstructor) {
 222         this.foundNonPubConstructor = foundNonPubConstructor;
 223     }
 224 
 225     /**
 226      * {@inheritDoc}
 227      */
 228     @Override
 229     public void addSummaryLabel(Content memberTree) {
 230         Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING,
 231                 contents.constructorSummaryLabel);
 232         memberTree.addContent(label);
 233     }
 234 
 235     /**
 236      * {@inheritDoc}
 237      */
 238     @Override
 239     public String getTableSummary() {
 240         return resources.getText("doclet.Member_Table_Summary",
 241                 resources.getText("doclet.Constructor_Summary"),
 242                 resources.getText("doclet.constructors"));
 243     }
 244 
 245     /**
 246      * {@inheritDoc}
 247      */
 248     @Override
 249     public TableHeader getSummaryTableHeader(Element member) {
 250         if (foundNonPubConstructor) {
 251             return new TableHeader(contents.modifierLabel, contents.constructorLabel,
 252                     contents.descriptionLabel);
 253         } else {
 254             return new TableHeader(contents.constructorLabel, contents.descriptionLabel);
 255         }
 256     }
 257 
 258     @Override
 259     protected Table createSummaryTable() {
 260         List<HtmlStyle> bodyRowStyles;
 261         int rowScopeColumn;
 262 
 263         if (foundNonPubConstructor) {
 264             bodyRowStyles = Arrays.asList(HtmlStyle.colFirst, HtmlStyle.colConstructorName,
 265                     HtmlStyle.colLast);
 266             rowScopeColumn = 1;
 267         } else {
 268             bodyRowStyles = Arrays.asList(HtmlStyle.colConstructorName, HtmlStyle.colLast);
 269             rowScopeColumn = 0;
 270         }
 271 
 272         return new Table(configuration.htmlVersion, HtmlStyle.memberSummary)
 273                 .setSummary(getTableSummary())
 274                 .setCaption(contents.constructors)
 275                 .setHeader(getSummaryTableHeader(typeElement))
 276                 .setRowScopeColumn(rowScopeColumn)
 277                 .setColumnStyles(bodyRowStyles)
 278                 .setUseTBody(false);  // temporary? compatibility mode for TBody
 279     }
 280 
 281     /**
 282      * {@inheritDoc}
 283      */
 284     @Override
 285     public void addSummaryAnchor(TypeElement typeElement, Content memberTree) {
 286         memberTree.addContent(writer.getMarkerAnchor(
 287                 SectionName.CONSTRUCTOR_SUMMARY));
 288     }
 289 
 290     /**
 291      * {@inheritDoc}
 292      */
 293     @Override
 294     public void addInheritedSummaryAnchor(TypeElement typeElement, Content inheritedTree) {
 295     }
 296 
 297     /**
 298      * {@inheritDoc}
 299      */
 300     @Override
 301     public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
 302     }
 303 
 304     /**
 305      * {@inheritDoc}
 306      */
 307     @Override
 308     protected Content getNavSummaryLink(TypeElement typeElement, boolean link) {
 309         if (link) {
 310             return writer.getHyperLink(SectionName.CONSTRUCTOR_SUMMARY,
 311                     contents.navConstructor);
 312         } else {
 313             return contents.navConstructor;
 314         }
 315     }
 316 
 317     /**
 318      * {@inheritDoc}
 319      */
 320     @Override
 321     protected void addNavDetailLink(boolean link, Content liNav) {
 322         if (link) {
 323             liNav.addContent(writer.getHyperLink(
 324                     SectionName.CONSTRUCTOR_DETAIL,
 325                     contents.navConstructor));
 326         } else {
 327             liNav.addContent(contents.navConstructor);
 328         }
 329     }
 330 
 331     /**
 332      * {@inheritDoc}
 333      */
 334     @Override
 335     protected void addSummaryType(Element member, Content tdSummaryType) {
 336         if (foundNonPubConstructor) {
 337             Content code = new HtmlTree(HtmlTag.CODE);
 338             if (utils.isProtected(member)) {
 339                 code.addContent("protected ");
 340             } else if (utils.isPrivate(member)) {
 341                 code.addContent("private ");
 342             } else if (utils.isPublic(member)) {
 343                 code.addContent(Contents.SPACE);
 344             } else {
 345                 code.addContent(
 346                         configuration.getText("doclet.Package_private"));
 347             }
 348             tdSummaryType.addContent(code);
 349         }
 350     }
 351 }