src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java

Print this page


   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.formats.html;
  27 
  28 import com.sun.javadoc.*;
  29 import com.sun.tools.doclets.formats.html.markup.ContentBuilder;
  30 import com.sun.tools.doclets.formats.html.markup.HtmlStyle;
  31 import com.sun.tools.doclets.formats.html.markup.HtmlTree;
  32 import com.sun.tools.doclets.formats.html.markup.RawHtml;
  33 import com.sun.tools.doclets.formats.html.markup.StringContent;
  34 import com.sun.tools.doclets.internal.toolkit.*;
  35 import com.sun.tools.doclets.internal.toolkit.builders.SerializedFormBuilder;
  36 import com.sun.tools.doclets.internal.toolkit.taglets.*;
  37 import com.sun.tools.doclets.internal.toolkit.util.*;
  38 





















  39 /**
  40  * The taglet writer that writes HTML.
  41  *
  42  *  <p><b>This is NOT part of any supported API.
  43  *  If you write code that depends on this, you do so at your own risk.
  44  *  This code and its internal interfaces are subject to change or
  45  *  deletion without notice.</b>
  46  *
  47  * @since 1.5
  48  * @author Jamie Ho
  49  * @author Bhavesh Patel (Modified)
  50  */
  51 
  52 public class TagletWriterImpl extends TagletWriter {
  53 
  54     private final HtmlDocletWriter htmlWriter;
  55     private final ConfigurationImpl configuration;
  56     private final Utils utils;
  57 
  58     public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence) {
  59         super(isFirstSentence);
  60         this.htmlWriter = htmlWriter;
  61         configuration = htmlWriter.configuration;
  62         this.utils = configuration.utils;
  63     }
  64 
  65     /**
  66      * {@inheritDoc}
  67      */
  68     public Content getOutputInstance() {
  69         return new ContentBuilder();
  70     }
  71 
  72     /**
  73      * {@inheritDoc}
  74      */
  75     protected Content codeTagOutput(Tag tag) {
  76         Content result = HtmlTree.CODE(new StringContent(utils.normalizeNewlines(tag.text())));



  77         return result;
  78     }
  79 
  80     protected Content indexTagOutput(Tag tag) {
  81         String text = tag.text();
  82         String tagText = "";
  83         String desc = "";
  84         if (text.isEmpty() || text.trim().isEmpty()) {
  85             configuration.message.warning(tag.position(), "doclet.invalid_usage_of_tag", tag.name());
  86         } else {
  87             int len = text.length();
  88             int tagTextEnd = 0;
  89             int descstart = 0;
  90             int start = 0;
  91             Character term = ' ';
  92             int cp = text.codePointAt(0);
  93             if (cp == '"') {
  94                 term = '"';
  95                 start++;
  96             }
  97             for (int i = start; i < len; i += Character.charCount(cp)) {
  98                 cp = text.codePointAt(i);
  99                 if (cp == term) {
 100                     tagTextEnd = i;
 101                     break;
 102                 }
 103             }
 104             if (tagTextEnd < len - 1 && tagTextEnd != 0) {
 105                 descstart = tagTextEnd + 1;
 106             }
 107             String desctext = "";
 108             if (descstart > 0) {
 109                 tagText = text.substring(start, tagTextEnd).trim();
 110                 desctext = text.substring(descstart, len).trim();
 111                 // strip off the white space which can be between tag description and the
 112                 // actual label.
 113                 for (int i = 0; i < desctext.length(); i++) {
 114                     char ch2 = desctext.charAt(i);
 115                     if (!(ch2 == ' ' || ch2 == '\t' || ch2 == '\n')) {
 116                         desc = desctext.substring(i);
 117                         break;
 118                     }
 119                 }
 120             } else {
 121                 if (term == '"') {
 122                     if (tagTextEnd == 0) {
 123                         // If unclosed quote, print out a warning and ignore the invalid tag text.
 124                         configuration.message.warning(tag.position(), "doclet.invalid_usage_of_tag", tag.name());
 125                         tagText = "";
 126                     } else {
 127                         tagText = text.substring(start, tagTextEnd).trim();
 128                     }
 129                 } else {
 130                     tagText = text.trim();
 131                 }
 132                 desc = "";
 133             }
 134         }
 135         String anchorName = htmlWriter.getName(tagText);
 136         Content result = HtmlTree.A_ID(anchorName, new StringContent(tagText));
 137         if (configuration.createindex && !tagText.isEmpty()) {
 138             SearchIndexItem si = new SearchIndexItem();
 139             si.setLabel(tagText);
 140             si.setDescription(desc);
 141             if (tag.holder() instanceof ProgramElementDoc) {
 142                 if (tag.holder() instanceof MemberDoc) {
 143                     si.setUrl(DocPath.forClass(((MemberDoc) tag.holder()).containingClass()).getPath()
 144                             + "#" + anchorName);
 145                     si.setHolder(((MemberDoc) tag.holder()).qualifiedName());
 146                 } else {
 147                     si.setUrl(DocPath.forClass((ClassDoc) tag.holder()).getPath() + "#" + anchorName);
 148                     si.setHolder(((ClassDoc) tag.holder()).qualifiedName());
 149                 }
 150             } else if (tag.holder() instanceof PackageDoc) {
 151                 si.setUrl(DocPath.forPackage((PackageDoc) tag.holder()).getPath()
 152                         + "/" + DocPaths.PACKAGE_SUMMARY.getPath() + "#" + anchorName);
 153                 si.setHolder(((PackageDoc) tag.holder()).name());

 154             }
























 155             si.setCategory(configuration.getResource("doclet.SearchTags").toString());
 156             configuration.tagSearchIndex.add(si);
 157         }
 158         return result;
 159     }
 160 
 161     /**
 162      * {@inheritDoc}
 163      */
 164     public Content getDocRootOutput() {
 165         String path;
 166         if (htmlWriter.pathToRoot.isEmpty())
 167             path = ".";
 168         else
 169             path = htmlWriter.pathToRoot.getPath();
 170         return new StringContent(path);
 171     }
 172 
 173     /**
 174      * {@inheritDoc}
 175      */
 176     public Content deprecatedTagOutput(Doc doc) {
 177         ContentBuilder result = new ContentBuilder();
 178         Tag[] deprs = doc.tags("deprecated");
 179         if (doc instanceof ClassDoc) {
 180             if (utils.isDeprecated((ProgramElementDoc) doc)) {

 181                 result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 182                         new StringContent(configuration.getText("doclet.Deprecated"))));
 183                 result.addContent(RawHtml.nbsp);
 184                 if (deprs.length > 0) {
 185                     Tag[] commentTags = deprs[0].inlineTags();
 186                     if (commentTags.length > 0) {
 187                         result.addContent(commentTagsToOutput(null, doc,
 188                             deprs[0].inlineTags(), false)
 189                         );
 190                     }
 191                 }
 192             }
 193         } else {
 194             MemberDoc member = (MemberDoc) doc;
 195             if (utils.isDeprecated((ProgramElementDoc) doc)) {
 196                 result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 197                         new StringContent(configuration.getText("doclet.Deprecated"))));
 198                 result.addContent(RawHtml.nbsp);
 199                 if (deprs.length > 0) {
 200                     Content body = commentTagsToOutput(null, doc,
 201                         deprs[0].inlineTags(), false);
 202                     if (!body.isEmpty())
 203                         result.addContent(HtmlTree.SPAN(HtmlStyle.deprecationComment, body));
 204                 }
 205             } else {
 206                 if (utils.isDeprecated(member.containingClass())) {
 207                     result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 208                             new StringContent(configuration.getText("doclet.Deprecated"))));
 209                     result.addContent(RawHtml.nbsp);
 210                 }
 211             }
 212         }
 213         return result;
 214     }
 215 
 216     /**
 217      * {@inheritDoc}
 218      */
 219     protected Content literalTagOutput(Tag tag) {
 220         Content result = new StringContent(utils.normalizeNewlines(tag.text()));

 221         return result;
 222     }
 223 
 224     /**
 225      * {@inheritDoc}
 226      */
 227     public MessageRetriever getMsgRetriever() {
 228         return configuration.message;
 229     }
 230 
 231     /**
 232      * {@inheritDoc}
 233      */
 234     public Content getParamHeader(String header) {
 235         HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.paramLabel,
 236                 new StringContent(header)));
 237         return result;
 238     }
 239 
 240     /**
 241      * {@inheritDoc}
 242      */
 243     public Content paramTagOutput(ParamTag paramTag, String paramName) {
 244         ContentBuilder body = new ContentBuilder();

 245         body.addContent(HtmlTree.CODE(new RawHtml(paramName)));
 246         body.addContent(" - ");
 247         body.addContent(htmlWriter.commentTagsToContent(paramTag, null, paramTag.inlineTags(), false));

 248         HtmlTree result = HtmlTree.DD(body);
 249         return result;
 250     }
 251 
 252     /**
 253      * {@inheritDoc}
 254      */
 255     public Content propertyTagOutput(Tag tag, String prefix) {
 256         Content body = new ContentBuilder();

 257         body.addContent(new RawHtml(prefix));
 258         body.addContent(" ");
 259         body.addContent(HtmlTree.CODE(new RawHtml(tag.text())));
 260         body.addContent(".");
 261         Content result = HtmlTree.P(body);
 262         return result;
 263     }
 264 
 265     /**
 266      * {@inheritDoc}
 267      */
 268     public Content returnTagOutput(Tag returnTag) {
 269         ContentBuilder result = new ContentBuilder();

 270         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.returnLabel,
 271                 new StringContent(configuration.getText("doclet.Returns")))));
 272         result.addContent(HtmlTree.DD(htmlWriter.commentTagsToContent(
 273                 returnTag, null, returnTag.inlineTags(), false)));
 274         return result;
 275     }
 276 
 277     /**
 278      * {@inheritDoc}
 279      */
 280     public Content seeTagOutput(Doc holder, SeeTag[] seeTags) {
 281         ContentBuilder body = new ContentBuilder();
 282         if (seeTags.length > 0) {
 283             for (SeeTag seeTag : seeTags) {
 284                 appendSeparatorIfNotEmpty(body);
 285                 body.addContent(htmlWriter.seeTagToContent(seeTag));
 286             }
 287         }
 288         if (holder.isField() && ((FieldDoc)holder).constantValue() != null &&
 289                 htmlWriter instanceof ClassWriterImpl) {
 290             //Automatically add link to constant values page for constant fields.
 291             appendSeparatorIfNotEmpty(body);
 292             DocPath constantsPath =
 293                     htmlWriter.pathToRoot.resolve(DocPaths.CONSTANT_VALUES);
 294             String whichConstant =
 295                     ((ClassWriterImpl) htmlWriter).getClassDoc().qualifiedName() + "." + ((FieldDoc) holder).name();

 296             DocLink link = constantsPath.fragment(whichConstant);
 297             body.addContent(htmlWriter.getHyperLink(link,
 298                     new StringContent(configuration.getText("doclet.Constants_Summary"))));
 299         }
 300         if (holder.isClass() && ((ClassDoc)holder).isSerializable()) {
 301             //Automatically add link to serialized form page for serializable classes.
 302             if ((SerializedFormBuilder.serialInclude(holder) &&
 303                       SerializedFormBuilder.serialInclude(((ClassDoc)holder).containingPackage()))) {
 304                 appendSeparatorIfNotEmpty(body);
 305                 DocPath serialPath = htmlWriter.pathToRoot.resolve(DocPaths.SERIALIZED_FORM);
 306                 DocLink link = serialPath.fragment(((ClassDoc)holder).qualifiedName());
 307                 body.addContent(htmlWriter.getHyperLink(link,
 308                         new StringContent(configuration.getText("doclet.Serialized_Form"))));
 309             }
 310         }
 311         if (body.isEmpty())
 312             return body;
 313 
 314         ContentBuilder result = new ContentBuilder();
 315         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.seeLabel,
 316                 new StringContent(configuration.getText("doclet.See_Also")))));
 317         result.addContent(HtmlTree.DD(body));
 318         return result;
 319 
 320     }
 321 
 322     private void appendSeparatorIfNotEmpty(ContentBuilder body) {
 323         if (!body.isEmpty()) {
 324             body.addContent(", ");
 325             body.addContent(DocletConstants.NL);
 326         }
 327     }
 328 
 329     /**
 330      * {@inheritDoc}
 331      */
 332     public Content simpleTagOutput(Tag[] simpleTags, String header) {

 333         ContentBuilder result = new ContentBuilder();
 334         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
 335         ContentBuilder body = new ContentBuilder();
 336         for (int i = 0; i < simpleTags.length; i++) {
 337             if (i > 0) {

 338                 body.addContent(", ");
 339             }
 340             body.addContent(htmlWriter.commentTagsToContent(
 341                     simpleTags[i], null, simpleTags[i].inlineTags(), false));

 342         }
 343         result.addContent(HtmlTree.DD(body));
 344         return result;
 345     }
 346 
 347     /**
 348      * {@inheritDoc}
 349      */
 350     public Content simpleTagOutput(Tag simpleTag, String header) {
 351         ContentBuilder result = new ContentBuilder();
 352         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
 353         Content body = htmlWriter.commentTagsToContent(
 354                 simpleTag, null, simpleTag.inlineTags(), false);

 355         result.addContent(HtmlTree.DD(body));
 356         return result;
 357     }
 358 
 359     /**
 360      * {@inheritDoc}
 361      */
 362     public Content getThrowsHeader() {
 363         HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.throwsLabel,
 364                 new StringContent(configuration.getText("doclet.Throws"))));
 365         return result;
 366     }
 367 
 368     /**
 369      * {@inheritDoc}
 370      */
 371     public Content throwsTagOutput(ThrowsTag throwsTag) {
 372         ContentBuilder body = new ContentBuilder();
 373         Content excName = (throwsTag.exceptionType() == null) ?
 374                 new RawHtml(throwsTag.exceptionName()) :
 375                 htmlWriter.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
 376                 throwsTag.exceptionType()));









 377         body.addContent(HtmlTree.CODE(excName));
 378         Content desc = htmlWriter.commentTagsToContent(throwsTag, null,
 379             throwsTag.inlineTags(), false);
 380         if (desc != null && !desc.isEmpty()) {
 381             body.addContent(" - ");
 382             body.addContent(desc);
 383         }
 384         HtmlTree result = HtmlTree.DD(body);
 385         return result;
 386     }
 387 
 388     /**
 389      * {@inheritDoc}
 390      */
 391     public Content throwsTagOutput(Type throwsType) {
 392         HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink(
 393                 new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, throwsType))));
 394         return result;
 395     }
 396 
 397     /**
 398      * {@inheritDoc}
 399      */
 400     public Content valueTagOutput(FieldDoc field, String constantVal,
 401             boolean includeLink) {
 402         return includeLink ?
 403             htmlWriter.getDocLink(LinkInfoImpl.Kind.VALUE_TAG, field,
 404                 constantVal, false) : new RawHtml(constantVal);
 405     }
 406 
 407     /**
 408      * {@inheritDoc}
 409      */
 410     public Content commentTagsToOutput(Tag holderTag, Tag[] tags) {
 411         return commentTagsToOutput(holderTag, null, tags, false);
 412     }
 413 
 414     /**
 415      * {@inheritDoc}
 416      */
 417     public Content commentTagsToOutput(Doc holderDoc, Tag[] tags) {
 418         return commentTagsToOutput(null, holderDoc, tags, false);
 419     }
 420 
 421     /**
 422      * {@inheritDoc}
 423      */
 424     public Content commentTagsToOutput(Tag holderTag,
 425         Doc holderDoc, Tag[] tags, boolean isFirstSentence) {
 426         return htmlWriter.commentTagsToContent(
 427             holderTag, holderDoc, tags, isFirstSentence);
 428     }
 429 
 430     /**
 431      * {@inheritDoc}
 432      */
 433     public Configuration configuration() {
 434         return configuration;
 435     }
 436 }
   1 /*
   2  * Copyright (c) 2003, 2015, 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 java.util.List;
  29 import javax.lang.model.element.Element;
  30 import javax.lang.model.element.PackageElement;
  31 import javax.lang.model.element.TypeElement;
  32 import javax.lang.model.element.VariableElement;
  33 import javax.lang.model.type.TypeMirror;
  34 import javax.lang.model.util.SimpleElementVisitor9;



  35 
  36 import com.sun.source.doctree.DocTree;
  37 import com.sun.source.doctree.IndexTree;
  38 import com.sun.tools.javac.util.DefinedBy;
  39 
  40 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
  41 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
  42 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
  43 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
  44 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
  45 import jdk.javadoc.internal.doclets.toolkit.Configuration;
  46 import jdk.javadoc.internal.doclets.toolkit.Content;
  47 import jdk.javadoc.internal.doclets.toolkit.builders.SerializedFormBuilder;
  48 import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter;
  49 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
  50 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
  51 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
  52 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
  53 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
  54 import jdk.javadoc.internal.doclets.toolkit.util.MessageRetriever;
  55 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
  56 
  57 /**
  58  * The taglet writer that writes HTML.
  59  *
  60  *  <p><b>This is NOT part of any supported API.
  61  *  If you write code that depends on this, you do so at your own risk.
  62  *  This code and its internal interfaces are subject to change or
  63  *  deletion without notice.</b>
  64  *
  65  * @since 1.5
  66  * @author Jamie Ho
  67  * @author Bhavesh Patel (Modified)
  68  */
  69 
  70 public class TagletWriterImpl extends TagletWriter {
  71 
  72     private final HtmlDocletWriter htmlWriter;
  73     private final ConfigurationImpl configuration;
  74     private final Utils utils;
  75 
  76     public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence) {
  77         super(isFirstSentence);
  78         this.htmlWriter = htmlWriter;
  79         configuration = htmlWriter.configuration;
  80         this.utils = configuration.utils;
  81     }
  82 
  83     /**
  84      * {@inheritDoc}
  85      */
  86     public Content getOutputInstance() {
  87         return new ContentBuilder();
  88     }
  89 
  90     /**
  91      * {@inheritDoc}
  92      */
  93     protected Content codeTagOutput(Element element, DocTree tag) {
  94         CommentHelper ch = utils.getCommentHelper(element);
  95         String str = utils.normalizeNewlines(ch.getText(tag));
  96         StringContent content = new StringContent(str);
  97         Content result = HtmlTree.CODE(content);
  98         return result;
  99     }
 100 
 101     protected Content indexTagOutput(Element element, DocTree tag) {
 102         CommentHelper ch = utils.getCommentHelper(element);
 103         IndexTree itt = (IndexTree)tag;
 104 
 105         String tagText =  ch.getText(itt.getSearchTerm());
 106         if (tagText.charAt(0) == '"' && tagText.charAt(tagText.length() - 1) == '"') {
 107             tagText = tagText.substring(1, tagText.length() - 1);









 108         }
 109         String desc = ch.getText(itt.getDescription());
 110 




































 111         String anchorName = htmlWriter.getName(tagText);
 112         Content result = HtmlTree.A_ID(anchorName, new StringContent(tagText));
 113         if (configuration.createindex && !tagText.isEmpty()) {
 114             SearchIndexItem si = new SearchIndexItem();
 115             si.setLabel(tagText);
 116             si.setDescription(desc);
 117             new SimpleElementVisitor9<Void, Void>() {
 118                 @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
 119                 public Void visitPackage(PackageElement e, Void p) {
 120                     si.setUrl(DocPath.forPackage(e).getPath()







 121                             + "/" + DocPaths.PACKAGE_SUMMARY.getPath() + "#" + anchorName);
 122                     si.setHolder(utils.getSimpleName(element));
 123                     return null;
 124                 }
 125 
 126                 @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
 127                 public Void visitType(TypeElement e, Void p) {
 128                     si.setUrl(DocPath.forClass(utils, e).getPath() + "#" + anchorName);
 129                     si.setHolder(utils.getFullyQualifiedName(e));
 130                     return null;
 131                 }
 132 
 133                 @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
 134                 public Void visitVariable(VariableElement e, Void p) {
 135                     TypeElement te = utils.getEnclosingTypeElement(e);
 136                     si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName);
 137                     si.setHolder(utils.getFullyQualifiedName(e) + "." + utils.getSimpleName(e));
 138                     return null;
 139                 }
 140 
 141                 @Override @DefinedBy(DefinedBy.Api.LANGUAGE_MODEL)
 142                 protected Void defaultAction(Element e, Void p) {
 143                     TypeElement te = utils.getEnclosingTypeElement(e);
 144                     si.setUrl(DocPath.forClass(utils, te).getPath() + "#" + anchorName);
 145                     si.setHolder(utils.getFullyQualifiedName(e));
 146                     return null;
 147                 }
 148             }.visit(element);
 149             si.setCategory(configuration.getResource("doclet.SearchTags").toString());
 150             configuration.tagSearchIndex.add(si);
 151         }
 152         return result;
 153     }
 154 
 155     /**
 156      * {@inheritDoc}
 157      */
 158     public Content getDocRootOutput() {
 159         String path;
 160         if (htmlWriter.pathToRoot.isEmpty())
 161             path = ".";
 162         else
 163             path = htmlWriter.pathToRoot.getPath();
 164         return new StringContent(path);
 165     }
 166 
 167     /**
 168      * {@inheritDoc}
 169      */
 170     public Content deprecatedTagOutput(Element element) {
 171         ContentBuilder result = new ContentBuilder();
 172         CommentHelper ch = utils.getCommentHelper(element);
 173         List<? extends DocTree> deprs = utils.getBlockTags(element, DocTree.Kind.DEPRECATED);
 174         if (utils.isTypeElement(element)) {
 175             if (utils.isDeprecated(element)) {
 176                 result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 177                         new StringContent(configuration.getText("doclet.Deprecated"))));
 178                 result.addContent(RawHtml.nbsp);
 179                 if (!deprs.isEmpty()) {
 180                     List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
 181                     if (!commentTags.isEmpty()) {
 182                         result.addContent(commentTagsToOutput(null, element, commentTags, false));


 183                     }
 184                 }
 185             }
 186         } else {
 187             if (utils.isDeprecated(element)) {

 188                 result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 189                         new StringContent(configuration.getText("doclet.Deprecated"))));
 190                 result.addContent(RawHtml.nbsp);
 191                 if (!deprs.isEmpty()) {
 192                     List<? extends DocTree> bodyTags = ch.getBody(configuration, deprs.get(0));
 193                     Content body = commentTagsToOutput(null, element, bodyTags, false);
 194                     if (!body.isEmpty())
 195                         result.addContent(HtmlTree.SPAN(HtmlStyle.deprecationComment, body));
 196                 }
 197             } else {
 198                 if (utils.isDeprecated(utils.getEnclosingTypeElement(element))) {
 199                     result.addContent(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
 200                             new StringContent(configuration.getText("doclet.Deprecated"))));
 201                     result.addContent(RawHtml.nbsp);
 202                 }
 203             }
 204         }
 205         return result;
 206     }
 207 
 208     /**
 209      * {@inheritDoc}
 210      */
 211     protected Content literalTagOutput(Element element, DocTree tag) {
 212         CommentHelper ch = utils.getCommentHelper(element);
 213         Content result = new StringContent(utils.normalizeNewlines(ch.getText(tag)));
 214         return result;
 215     }
 216 
 217     /**
 218      * {@inheritDoc}
 219      */
 220     public MessageRetriever getMsgRetriever() {
 221         return configuration.message;
 222     }
 223 
 224     /**
 225      * {@inheritDoc}
 226      */
 227     public Content getParamHeader(String header) {
 228         HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.paramLabel,
 229                 new StringContent(header)));
 230         return result;
 231     }
 232 
 233     /**
 234      * {@inheritDoc}
 235      */
 236     public Content paramTagOutput(Element element, DocTree paramTag, String paramName) {
 237         ContentBuilder body = new ContentBuilder();
 238         CommentHelper ch = utils.getCommentHelper(element);
 239         body.addContent(HtmlTree.CODE(new RawHtml(paramName)));
 240         body.addContent(" - ");
 241         List<? extends DocTree> description = ch.getDescription(configuration, paramTag);
 242         body.addContent(htmlWriter.commentTagsToContent(paramTag, element, description, false));
 243         HtmlTree result = HtmlTree.DD(body);
 244         return result;
 245     }
 246 
 247     /**
 248      * {@inheritDoc}
 249      */
 250     public Content propertyTagOutput(Element element, DocTree tag, String prefix) {
 251         Content body = new ContentBuilder();
 252         CommentHelper ch = utils.getCommentHelper(element);
 253         body.addContent(new RawHtml(prefix));
 254         body.addContent(" ");
 255         body.addContent(HtmlTree.CODE(new RawHtml(ch.getText(tag))));
 256         body.addContent(".");
 257         Content result = HtmlTree.P(body);
 258         return result;
 259     }
 260 
 261     /**
 262      * {@inheritDoc}
 263      */
 264     public Content returnTagOutput(Element element, DocTree returnTag) {
 265         ContentBuilder result = new ContentBuilder();
 266         CommentHelper ch = utils.getCommentHelper(element);
 267         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.returnLabel,
 268                 new StringContent(configuration.getText("doclet.Returns")))));
 269         result.addContent(HtmlTree.DD(htmlWriter.commentTagsToContent(
 270                 returnTag, element, ch.getDescription(configuration, returnTag), false)));
 271         return result;
 272     }
 273 
 274     /**
 275      * {@inheritDoc}
 276      */
 277     public Content seeTagOutput(Element holder, List<? extends DocTree> seeTags) {
 278         ContentBuilder body = new ContentBuilder();
 279         if (!seeTags.isEmpty()) {
 280             for (DocTree dt : seeTags) {
 281                 appendSeparatorIfNotEmpty(body);
 282                 body.addContent(htmlWriter.seeTagToContent(holder, dt));
 283             }
 284         }
 285         if (utils.isVariableElement(holder) && ((VariableElement)holder).getConstantValue() != null &&
 286                 htmlWriter instanceof ClassWriterImpl) {
 287             //Automatically add link to constant values page for constant fields.
 288             appendSeparatorIfNotEmpty(body);
 289             DocPath constantsPath =
 290                     htmlWriter.pathToRoot.resolve(DocPaths.CONSTANT_VALUES);
 291             String whichConstant =
 292                     ((ClassWriterImpl) htmlWriter).getTypeElement().getQualifiedName() + "." +
 293                     utils.getSimpleName(holder);
 294             DocLink link = constantsPath.fragment(whichConstant);
 295             body.addContent(htmlWriter.getHyperLink(link,
 296                     new StringContent(configuration.getText("doclet.Constants_Summary"))));
 297         }
 298         if (utils.isClass(holder) && utils.isSerializable((TypeElement)holder)) {
 299             //Automatically add link to serialized form page for serializable classes.
 300             if (SerializedFormBuilder.serialInclude(utils, holder) &&
 301                       SerializedFormBuilder.serialInclude(utils, utils.containingPackage(holder))) {
 302                 appendSeparatorIfNotEmpty(body);
 303                 DocPath serialPath = htmlWriter.pathToRoot.resolve(DocPaths.SERIALIZED_FORM);
 304                 DocLink link = serialPath.fragment(utils.getFullyQualifiedName(holder));
 305                 body.addContent(htmlWriter.getHyperLink(link,
 306                         new StringContent(configuration.getText("doclet.Serialized_Form"))));
 307             }
 308         }
 309         if (body.isEmpty())
 310             return body;
 311 
 312         ContentBuilder result = new ContentBuilder();
 313         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.seeLabel,
 314                 new StringContent(configuration.getText("doclet.See_Also")))));
 315         result.addContent(HtmlTree.DD(body));
 316         return result;
 317 
 318     }
 319 
 320     private void appendSeparatorIfNotEmpty(ContentBuilder body) {
 321         if (!body.isEmpty()) {
 322             body.addContent(", ");
 323             body.addContent(DocletConstants.NL);
 324         }
 325     }
 326 
 327     /**
 328      * {@inheritDoc}
 329      */
 330     public Content simpleTagOutput(Element element, List<? extends DocTree> simpleTags, String header) {
 331         CommentHelper ch = utils.getCommentHelper(element);
 332         ContentBuilder result = new ContentBuilder();
 333         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
 334         ContentBuilder body = new ContentBuilder();
 335         boolean many = false;
 336         for (DocTree simpleTag : simpleTags) {
 337             if (many) {
 338                 body.addContent(", ");
 339             }
 340             List<? extends DocTree> bodyTags = ch.getBody(configuration, simpleTag);
 341             body.addContent(htmlWriter.commentTagsToContent(simpleTag, element, bodyTags, false));
 342             many = true;
 343         }
 344         result.addContent(HtmlTree.DD(body));
 345         return result;
 346     }
 347 
 348     /**
 349      * {@inheritDoc}
 350      */
 351     public Content simpleTagOutput(Element element, DocTree simpleTag, String header) {
 352         ContentBuilder result = new ContentBuilder();
 353         result.addContent(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
 354         CommentHelper ch = utils.getCommentHelper(element);
 355         List<? extends DocTree> description = ch.getDescription(configuration, simpleTag);
 356         Content body = htmlWriter.commentTagsToContent(simpleTag, element, description, false);
 357         result.addContent(HtmlTree.DD(body));
 358         return result;
 359     }
 360 
 361     /**
 362      * {@inheritDoc}
 363      */
 364     public Content getThrowsHeader() {
 365         HtmlTree result = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.throwsLabel,
 366                 new StringContent(configuration.getText("doclet.Throws"))));
 367         return result;
 368     }
 369 
 370     /**
 371      * {@inheritDoc}
 372      */
 373     public Content throwsTagOutput(Element element, DocTree throwsTag) {
 374         ContentBuilder body = new ContentBuilder();
 375         CommentHelper ch = utils.getCommentHelper(element);
 376         Element exception = ch.getException(configuration, throwsTag);
 377         Content excName;
 378         if (exception == null) {
 379             excName = new RawHtml(ch.getExceptionName(throwsTag).toString());
 380         } else if (exception.asType() == null) {
 381             excName = new RawHtml(utils.getFullyQualifiedName(exception));
 382         } else {
 383             LinkInfoImpl link = new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
 384                                                  exception.asType());
 385             link.excludeTypeBounds = true;
 386             excName = htmlWriter.getLink(link);
 387         }
 388         body.addContent(HtmlTree.CODE(excName));
 389         List<? extends DocTree> description = ch.getDescription(configuration, throwsTag);
 390         Content desc = htmlWriter.commentTagsToContent(throwsTag, element, description, false);
 391         if (desc != null && !desc.isEmpty()) {
 392             body.addContent(" - ");
 393             body.addContent(desc);
 394         }
 395         HtmlTree result = HtmlTree.DD(body);
 396         return result;
 397     }
 398 
 399     /**
 400      * {@inheritDoc}
 401      */
 402     public Content throwsTagOutput(TypeMirror throwsType) {
 403         HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink(
 404                 new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, throwsType))));
 405         return result;
 406     }
 407 
 408     /**
 409      * {@inheritDoc}
 410      */
 411     public Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink) {

 412         return includeLink ?
 413             htmlWriter.getDocLink(LinkInfoImpl.Kind.VALUE_TAG, field,
 414                 constantVal, false) : new RawHtml(constantVal);
 415     }
 416 
 417     /**
 418      * {@inheritDoc}
 419      */
 420     public Content commentTagsToOutput(DocTree holderTag, List<? extends DocTree> tags) {
 421         return commentTagsToOutput(holderTag, null, tags, false);
 422     }
 423 
 424     /**
 425      * {@inheritDoc}
 426      */
 427     public Content commentTagsToOutput(Element holder, List<? extends DocTree> tags) {
 428         return commentTagsToOutput(null, holder, tags, false);
 429     }
 430 
 431     /**
 432      * {@inheritDoc}
 433      */
 434     public Content commentTagsToOutput(DocTree holderTag,
 435         Element holder, List<? extends DocTree> tags, boolean isFirstSentence) {
 436         return htmlWriter.commentTagsToContent(holderTag, holder,
 437                 tags, isFirstSentence);
 438     }
 439 
 440     /**
 441      * {@inheritDoc}
 442      */
 443     public Configuration configuration() {
 444         return configuration;
 445     }
 446 }