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