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