src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocWriter.java
changeset 47216 71c04702a3d5
parent 46080 65ccd412049b
child 47321 da60bce4fc9f
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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.markup;
       
    27 
       
    28 import java.util.*;
       
    29 
       
    30 import javax.lang.model.element.ModuleElement;
       
    31 import javax.lang.model.element.PackageElement;
       
    32 import javax.lang.model.element.TypeElement;
       
    33 
       
    34 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
       
    35 import jdk.javadoc.internal.doclets.formats.html.SectionName;
       
    36 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
       
    37 import jdk.javadoc.internal.doclets.toolkit.Content;
       
    38 import jdk.javadoc.internal.doclets.toolkit.Messages;
       
    39 import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
       
    40 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
       
    41 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
       
    42 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
       
    43 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
       
    44 
       
    45 
       
    46 /**
       
    47  * Class for the Html Format Code Generation specific to JavaDoc.
       
    48  * This Class contains methods related to the Html Code Generation which
       
    49  * are used by the Sub-Classes in the package jdk.javadoc.internal.tool.standard.
       
    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 Atul M Dambalkar
       
    57  * @author Robert Field
       
    58  */
       
    59 public abstract class HtmlDocWriter extends HtmlWriter {
       
    60 
       
    61     public static final String CONTENT_TYPE = "text/html";
       
    62 
       
    63     DocPath pathToRoot;
       
    64 
       
    65     /**
       
    66      * Constructor. Initializes the destination file name through the super
       
    67      * class HtmlWriter.
       
    68      *
       
    69      * @param configuration the configuration for this doclet
       
    70      * @param filename String file name.
       
    71      */
       
    72     public HtmlDocWriter(BaseConfiguration configuration, DocPath filename) {
       
    73         super(configuration, filename);
       
    74         this.pathToRoot = filename.parent().invert();
       
    75         Messages messages = configuration.getMessages();
       
    76         messages.notice("doclet.Generating_0",
       
    77             DocFile.createFileForOutput(configuration, filename).getPath());
       
    78     }
       
    79 
       
    80     /**
       
    81      * Accessor for configuration.
       
    82      * @return the configuration for this doclet
       
    83      */
       
    84     public abstract BaseConfiguration configuration();
       
    85 
       
    86     public Content getHyperLink(DocPath link, String label) {
       
    87         return getHyperLink(link, new StringContent(label), false, "", "", "");
       
    88     }
       
    89 
       
    90     /**
       
    91      * Get Html Hyper Link Content.
       
    92      *
       
    93      * @param where      Position of the link in the file. Character '#' is not
       
    94      *                   needed.
       
    95      * @param label      Tag for the link.
       
    96      * @return a content tree for the hyper link
       
    97      */
       
    98     public Content getHyperLink(String where,
       
    99                                Content label) {
       
   100         return getHyperLink(getDocLink(where), label, "", "");
       
   101     }
       
   102 
       
   103     /**
       
   104      * Get Html Hyper Link Content.
       
   105      *
       
   106      * @param sectionName      The section name to which the link will be created.
       
   107      * @param label            Tag for the link.
       
   108      * @return a content tree for the hyper link
       
   109      */
       
   110     public Content getHyperLink(SectionName sectionName,
       
   111                                Content label) {
       
   112         return getHyperLink(getDocLink(sectionName), label, "", "");
       
   113     }
       
   114 
       
   115     /**
       
   116      * Get Html Hyper Link Content.
       
   117      *
       
   118      * @param sectionName      The section name combined with where to which the link
       
   119      *                         will be created.
       
   120      * @param where            The fragment combined with sectionName to which the link
       
   121      *                         will be created.
       
   122      * @param label            Tag for the link.
       
   123      * @return a content tree for the hyper link
       
   124      */
       
   125     public Content getHyperLink(SectionName sectionName, String where,
       
   126                                Content label) {
       
   127         return getHyperLink(getDocLink(sectionName, where), label, "", "");
       
   128     }
       
   129 
       
   130     /**
       
   131      * Get the link.
       
   132      *
       
   133      * @param where      Position of the link in the file.
       
   134      * @return a DocLink object for the hyper link
       
   135      */
       
   136     public DocLink getDocLink(String where) {
       
   137         return DocLink.fragment(getName(where));
       
   138     }
       
   139 
       
   140     /**
       
   141      * Get the link.
       
   142      *
       
   143      * @param sectionName      The section name to which the link will be created.
       
   144      * @return a DocLink object for the hyper link
       
   145      */
       
   146     public DocLink getDocLink(SectionName sectionName) {
       
   147         return DocLink.fragment(sectionName.getName());
       
   148     }
       
   149 
       
   150     /**
       
   151      * Get the link.
       
   152      *
       
   153      * @param sectionName      The section name combined with where to which the link
       
   154      *                         will be created.
       
   155      * @param where            The fragment combined with sectionName to which the link
       
   156      *                         will be created.
       
   157      * @return a DocLink object for the hyper link
       
   158      */
       
   159     public DocLink getDocLink(SectionName sectionName, String where) {
       
   160         return DocLink.fragment(sectionName.getName() + getName(where));
       
   161     }
       
   162 
       
   163     /**
       
   164      * Convert the name to a valid HTML name.
       
   165      *
       
   166      * @param name the name that needs to be converted to valid HTML name.
       
   167      * @return a valid HTML name string.
       
   168      */
       
   169     public String getName(String name) {
       
   170         StringBuilder sb = new StringBuilder();
       
   171         char ch;
       
   172         /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions
       
   173          * that the name/id should begin with a letter followed by other valid characters.
       
   174          * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction
       
   175          * is that it should be at least one character long and should not contain spaces.
       
   176          * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute.
       
   177          *
       
   178          * For HTML 4, we need to check for non-characters at the beginning of the name and
       
   179          * substitute it accordingly, "_" and "$" can appear at the beginning of a member name.
       
   180          * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z".
       
   181          */
       
   182         for (int i = 0; i < name.length(); i++) {
       
   183             ch = name.charAt(i);
       
   184             switch (ch) {
       
   185                 case '(':
       
   186                 case ')':
       
   187                 case '<':
       
   188                 case '>':
       
   189                 case ',':
       
   190                     sb.append('-');
       
   191                     break;
       
   192                 case ' ':
       
   193                 case '[':
       
   194                     break;
       
   195                 case ']':
       
   196                     sb.append(":A");
       
   197                     break;
       
   198                 // Any appearance of $ needs to be substituted with ":D" and not with hyphen
       
   199                 // since a field name "P$$ and a method P(), both valid member names, can end
       
   200                 // up as "P--". A member name beginning with $ needs to be substituted with
       
   201                 // "Z:Z:D".
       
   202                 case '$':
       
   203                     if (i == 0)
       
   204                         sb.append("Z:Z");
       
   205                     sb.append(":D");
       
   206                     break;
       
   207                 // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor
       
   208                 // names can only begin with a letter.
       
   209                 case '_':
       
   210                     if (i == 0)
       
   211                         sb.append("Z:Z");
       
   212                     sb.append(ch);
       
   213                     break;
       
   214                 default:
       
   215                     sb.append(ch);
       
   216             }
       
   217         }
       
   218         return sb.toString();
       
   219     }
       
   220 
       
   221     /**
       
   222      * Get Html hyperlink.
       
   223      *
       
   224      * @param link       path of the file.
       
   225      * @param label      Tag for the link.
       
   226      * @return a content tree for the hyper link
       
   227      */
       
   228     public Content getHyperLink(DocPath link, Content label) {
       
   229         return getHyperLink(link, label, "", "");
       
   230     }
       
   231 
       
   232     public Content getHyperLink(DocLink link, Content label) {
       
   233         return getHyperLink(link, label, "", "");
       
   234     }
       
   235 
       
   236     public Content getHyperLink(DocPath link,
       
   237                                Content label, boolean strong,
       
   238                                String stylename, String title, String target) {
       
   239         return getHyperLink(new DocLink(link), label, strong,
       
   240                 stylename, title, target);
       
   241     }
       
   242 
       
   243     public Content getHyperLink(DocLink link,
       
   244                                Content label, boolean strong,
       
   245                                String stylename, String title, String target) {
       
   246         Content body = label;
       
   247         if (strong) {
       
   248             body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body);
       
   249         }
       
   250         if (stylename != null && stylename.length() != 0) {
       
   251             HtmlTree t = new HtmlTree(HtmlTag.FONT, body);
       
   252             t.addAttr(HtmlAttr.CLASS, stylename);
       
   253             body = t;
       
   254         }
       
   255         HtmlTree l = HtmlTree.A(link.toString(), body);
       
   256         if (title != null && title.length() != 0) {
       
   257             l.addAttr(HtmlAttr.TITLE, title);
       
   258         }
       
   259         if (target != null && target.length() != 0) {
       
   260             l.addAttr(HtmlAttr.TARGET, target);
       
   261         }
       
   262         return l;
       
   263     }
       
   264 
       
   265     /**
       
   266      * Get Html Hyper Link.
       
   267      *
       
   268      * @param link       String name of the file.
       
   269      * @param label      Tag for the link.
       
   270      * @param title      String that describes the link's content for accessibility.
       
   271      * @param target     Target frame.
       
   272      * @return a content tree for the hyper link.
       
   273      */
       
   274     public Content getHyperLink(DocPath link, Content label, String title, String target) {
       
   275         return getHyperLink(new DocLink(link), label, title, target);
       
   276     }
       
   277 
       
   278     public Content getHyperLink(DocLink link, Content label, String title, String target) {
       
   279         HtmlTree anchor = HtmlTree.A(link.toString(), label);
       
   280         if (title != null && title.length() != 0) {
       
   281             anchor.addAttr(HtmlAttr.TITLE, title);
       
   282         }
       
   283         if (target != null && target.length() != 0) {
       
   284             anchor.addAttr(HtmlAttr.TARGET, target);
       
   285         }
       
   286         return anchor;
       
   287     }
       
   288 
       
   289     public Content getModuleFramesHyperLink(ModuleElement mdle, Content label, String target) {
       
   290         DocLink mdlLink = new DocLink(DocPaths.moduleFrame(mdle));
       
   291         DocLink mtFrameLink = new DocLink(DocPaths.moduleTypeFrame(mdle));
       
   292         DocLink cFrameLink = new DocLink(DocPaths.moduleSummary(mdle));
       
   293         HtmlTree anchor = HtmlTree.A(mdlLink.toString(), label);
       
   294         String onclickStr = "updateModuleFrame('" + mtFrameLink + "','" + cFrameLink + "');";
       
   295         anchor.addAttr(HtmlAttr.TARGET, target);
       
   296         anchor.addAttr(HtmlAttr.ONCLICK, onclickStr);
       
   297         return anchor;
       
   298     }
       
   299 
       
   300     /**
       
   301      * Get the enclosed name of the package
       
   302      *
       
   303      * @param te  TypeElement
       
   304      * @return the name
       
   305      */
       
   306     public String getEnclosingPackageName(TypeElement te) {
       
   307 
       
   308         PackageElement encl = configuration.utils.containingPackage(te);
       
   309         return (encl.isUnnamed()) ? "" : (encl.getQualifiedName() + ".");
       
   310     }
       
   311 
       
   312     /**
       
   313      * Print the frames version of the Html file header.
       
   314      * Called only when generating an HTML frames file.
       
   315      *
       
   316      * @param title Title of this HTML document
       
   317      * @param configuration the configuration object
       
   318      * @param body the body content tree to be added to the HTML document
       
   319      * @throws DocFileIOException if there is an error writing the frames document
       
   320      */
       
   321     public void printFramesDocument(String title, HtmlConfiguration configuration,
       
   322             HtmlTree body) throws DocFileIOException {
       
   323         Content htmlDocType = configuration.isOutputHtml5()
       
   324                 ? DocType.HTML5
       
   325                 : DocType.TRANSITIONAL;
       
   326         Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
       
   327         Content head = new HtmlTree(HtmlTag.HEAD);
       
   328         head.addContent(getGeneratedBy(!configuration.notimestamp));
       
   329         Content windowTitle = HtmlTree.TITLE(new StringContent(title));
       
   330         head.addContent(windowTitle);
       
   331         Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset);
       
   332         head.addContent(meta);
       
   333         head.addContent(getStyleSheetProperties(configuration));
       
   334         head.addContent(getFramesJavaScript());
       
   335         Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(),
       
   336                 head, body);
       
   337         Content htmlDocument = new HtmlDocument(htmlDocType,
       
   338                 htmlComment, htmlTree);
       
   339         write(htmlDocument);
       
   340     }
       
   341 
       
   342     /**
       
   343      * Returns a link to the stylesheet file.
       
   344      *
       
   345      * @param configuration the configuration for this doclet
       
   346      * @return an HtmlTree for the lINK tag which provides the stylesheet location
       
   347      */
       
   348     public HtmlTree getStyleSheetProperties(HtmlConfiguration configuration) {
       
   349         String stylesheetfile = configuration.stylesheetfile;
       
   350         DocPath stylesheet;
       
   351         if (stylesheetfile.isEmpty()) {
       
   352             stylesheet = DocPaths.STYLESHEET;
       
   353         } else {
       
   354             DocFile file = DocFile.createFileForInput(configuration, stylesheetfile);
       
   355             stylesheet = DocPath.create(file.getName());
       
   356         }
       
   357         HtmlTree link = HtmlTree.LINK("stylesheet", "text/css",
       
   358                 pathToRoot.resolve(stylesheet).getPath(),
       
   359                 "Style");
       
   360         return link;
       
   361     }
       
   362 
       
   363     protected Comment getGeneratedBy(boolean timestamp) {
       
   364         String text = "Generated by javadoc"; // marker string, deliberately not localized
       
   365         if (timestamp) {
       
   366             Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
       
   367             Date today = calendar.getTime();
       
   368             text += " ("+ configuration.getDocletSpecificBuildDate() + ") on " + today;
       
   369         }
       
   370         return new Comment(text);
       
   371     }
       
   372 }