duke@1: /* jjg@1737: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.doclets.formats.html.markup; duke@1: jjg@197: import java.io.*; jjg@197: import java.util.*; duke@1: duke@1: import com.sun.javadoc.*; jjg@1361: import com.sun.tools.doclets.formats.html.ConfigurationImpl; bpatel@2101: import com.sun.tools.doclets.formats.html.SectionName; jjg@197: import com.sun.tools.doclets.internal.toolkit.*; jjg@1412: import com.sun.tools.doclets.internal.toolkit.util.DocFile; jjg@1373: import com.sun.tools.doclets.internal.toolkit.util.DocLink; jjg@1372: import com.sun.tools.doclets.internal.toolkit.util.DocPath; duke@1: duke@1: duke@1: /** duke@1: * Class for the Html Format Code Generation specific to JavaDoc. duke@1: * This Class contains methods related to the Html Code Generation which duke@1: * are used by the Sub-Classes in the package com.sun.tools.doclets.standard duke@1: * and com.sun.tools.doclets.oneone. duke@1: * jjg@1359: *

This is NOT part of any supported API. jjg@1359: * If you write code that depends on this, you do so at your own risk. jjg@1359: * This code and its internal interfaces are subject to change or jjg@1359: * deletion without notice. jjg@1359: * duke@1: * @since 1.2 duke@1: * @author Atul M Dambalkar duke@1: * @author Robert Field duke@1: */ duke@1: public abstract class HtmlDocWriter extends HtmlWriter { duke@1: bpatel@1981: public static final String CONTENT_TYPE = "text/html"; bpatel@1981: duke@1: /** duke@1: * Constructor. Initializes the destination file name through the super duke@1: * class HtmlWriter. duke@1: * duke@1: * @param filename String file name. duke@1: */ jjg@1372: public HtmlDocWriter(Configuration configuration, DocPath filename) jjg@1372: throws IOException { jjg@1372: super(configuration, filename); duke@1: configuration.message.notice("doclet.Generating_0", jjg@1412: DocFile.createFileForOutput(configuration, filename).getPath()); duke@1: } duke@1: duke@1: /** duke@1: * Accessor for configuration. duke@1: */ duke@1: public abstract Configuration configuration(); duke@1: jjg@1740: public Content getHyperLink(DocPath link, String label) { jjg@1740: return getHyperLink(link, new StringContent(label), false, "", "", ""); jjg@1740: } jjg@1740: duke@1: /** bpatel@2101: * Get Html Hyper Link Content. duke@1: * jjg@1372: * @param where Position of the link in the file. Character '#' is not jjg@1372: * needed. jjg@1372: * @param label Tag for the link. jjg@1372: * @return a content tree for the hyper link jjg@1372: */ jjg@1372: public Content getHyperLink(String where, jjg@1372: Content label) { bpatel@2101: return getHyperLink(getDocLink(where), label, "", ""); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Get Html Hyper Link Content. bpatel@2101: * bpatel@2101: * @param sectionName The section name to which the link will be created. bpatel@2101: * @param label Tag for the link. bpatel@2101: * @return a content tree for the hyper link bpatel@2101: */ bpatel@2101: public Content getHyperLink(SectionName sectionName, bpatel@2101: Content label) { bpatel@2101: return getHyperLink(getDocLink(sectionName), label, "", ""); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Get Html Hyper Link Content. bpatel@2101: * bpatel@2101: * @param sectionName The section name combined with where to which the link bpatel@2101: * will be created. bpatel@2101: * @param where The fragment combined with sectionName to which the link bpatel@2101: * will be created. bpatel@2101: * @param label Tag for the link. bpatel@2101: * @return a content tree for the hyper link bpatel@2101: */ bpatel@2101: public Content getHyperLink(SectionName sectionName, String where, bpatel@2101: Content label) { bpatel@2101: return getHyperLink(getDocLink(sectionName, where), label, "", ""); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Get the link. bpatel@2101: * bpatel@2101: * @param where Position of the link in the file. bpatel@2101: * @return a DocLink object for the hyper link bpatel@2101: */ bpatel@2101: public DocLink getDocLink(String where) { bpatel@2101: return DocLink.fragment(getName(where)); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Get the link. bpatel@2101: * bpatel@2101: * @param sectionName The section name to which the link will be created. bpatel@2101: * @return a DocLink object for the hyper link bpatel@2101: */ bpatel@2101: public DocLink getDocLink(SectionName sectionName) { bpatel@2101: return DocLink.fragment(sectionName.getName()); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Get the link. bpatel@2101: * bpatel@2101: * @param sectionName The section name combined with where to which the link bpatel@2101: * will be created. bpatel@2101: * @param where The fragment combined with sectionName to which the link bpatel@2101: * will be created. bpatel@2101: * @return a DocLink object for the hyper link bpatel@2101: */ bpatel@2101: public DocLink getDocLink(SectionName sectionName, String where) { bpatel@2101: return DocLink.fragment(sectionName.getName() + getName(where)); bpatel@2101: } bpatel@2101: bpatel@2101: /** bpatel@2101: * Convert the name to a valid HTML name. bpatel@2101: * bpatel@2101: * @param name the name that needs to be converted to valid HTML name. bpatel@2101: * @return a valid HTML name string. bpatel@2101: */ bpatel@2101: public String getName(String name) { bpatel@2101: StringBuilder sb = new StringBuilder(); bpatel@2101: char ch; bpatel@2101: /* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions bpatel@2101: * that the name/id should begin with a letter followed by other valid characters. bpatel@2101: * The HTML 5 spec (draft) is more permissive on names/ids where the only restriction bpatel@2101: * is that it should be at least one character long and should not contain spaces. bpatel@2101: * The spec draft is @ http://www.w3.org/html/wg/drafts/html/master/dom.html#the-id-attribute. bpatel@2101: * bpatel@2101: * For HTML 4, we need to check for non-characters at the beginning of the name and bpatel@2101: * substitute it accordingly, "_" and "$" can appear at the beginning of a member name. bpatel@2101: * The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z". bpatel@2101: */ bpatel@2101: for (int i = 0; i < name.length(); i++) { bpatel@2101: ch = name.charAt(i); bpatel@2101: switch (ch) { bpatel@2101: case '(': bpatel@2101: case ')': bpatel@2101: case '<': bpatel@2101: case '>': bpatel@2101: case ',': bpatel@2101: sb.append('-'); bpatel@2101: break; bpatel@2101: case ' ': bpatel@2101: case '[': bpatel@2101: break; bpatel@2101: case ']': bpatel@2101: sb.append(":A"); bpatel@2101: break; bpatel@2101: // Any appearance of $ needs to be substituted with ":D" and not with hyphen bpatel@2101: // since a field name "P$$ and a method P(), both valid member names, can end bpatel@2101: // up as "P--". A member name beginning with $ needs to be substituted with bpatel@2101: // "Z:Z:D". bpatel@2101: case '$': bpatel@2101: if (i == 0) bpatel@2101: sb.append("Z:Z"); bpatel@2101: sb.append(":D"); bpatel@2101: break; bpatel@2101: // A member name beginning with _ needs to be prefixed with "Z:Z" since valid anchor bpatel@2101: // names can only begin with a letter. bpatel@2101: case '_': bpatel@2101: if (i == 0) bpatel@2101: sb.append("Z:Z"); bpatel@2101: sb.append(ch); bpatel@2101: break; bpatel@2101: default: bpatel@2101: sb.append(ch); bpatel@2101: } bpatel@2101: } bpatel@2101: return sb.toString(); jjg@1372: } jjg@1372: jjg@1372: /** jjg@1737: * Get Html hyperlink. jjg@1372: * jjg@1737: * @param link path of the file. bpatel@766: * @param label Tag for the link. bpatel@766: * @return a content tree for the hyper link bpatel@766: */ jjg@1737: public Content getHyperLink(DocPath link, Content label) { jjg@1373: return getHyperLink(link, label, "", ""); jjg@1373: } jjg@1373: jjg@1737: public Content getHyperLink(DocLink link, Content label) { jjg@1373: return getHyperLink(link, label, "", ""); duke@1: } duke@1: jjg@1740: public Content getHyperLink(DocPath link, jjg@1740: Content label, boolean strong, jjg@1740: String stylename, String title, String target) { jjg@1740: return getHyperLink(new DocLink(link), label, strong, jjg@1740: stylename, title, target); jjg@1740: } jjg@1740: jjg@1737: public Content getHyperLink(DocLink link, jjg@1737: Content label, boolean strong, jjg@1737: String stylename, String title, String target) { jjg@1737: Content body = label; jjg@1737: if (strong) { bpatel@2147: body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body); jjg@1737: } jjg@1737: if (stylename != null && stylename.length() != 0) { jjg@1737: HtmlTree t = new HtmlTree(HtmlTag.FONT, body); jjg@1737: t.addAttr(HtmlAttr.CLASS, stylename); jjg@1737: body = t; jjg@1737: } jjg@1737: HtmlTree l = HtmlTree.A(link.toString(), body); jjg@1737: if (title != null && title.length() != 0) { jjg@1737: l.addAttr(HtmlAttr.TITLE, title); jjg@1737: } jjg@1737: if (target != null && target.length() != 0) { jjg@1737: l.addAttr(HtmlAttr.TARGET, target); jjg@1737: } jjg@1737: return l; jjg@1737: } jjg@1737: duke@1: /** bpatel@766: * Get Html Hyper Link. duke@1: * duke@1: * @param link String name of the file. duke@1: * @param label Tag for the link. bpatel@766: * @param title String that describes the link's content for accessibility. bpatel@766: * @param target Target frame. bpatel@766: * @return a content tree for the hyper link. duke@1: */ jjg@1373: public Content getHyperLink(DocPath link, jjg@1372: Content label, String title, String target) { jjg@1373: return getHyperLink(new DocLink(link), label, title, target); jjg@1372: } jjg@1373: jjg@1373: public Content getHyperLink(DocLink link, bpatel@766: Content label, String title, String target) { jjg@1373: HtmlTree anchor = HtmlTree.A(link.toString(), label); bpatel@766: if (title != null && title.length() != 0) { bpatel@766: anchor.addAttr(HtmlAttr.TITLE, title); bpatel@766: } bpatel@766: if (target != null && target.length() != 0) { bpatel@766: anchor.addAttr(HtmlAttr.TARGET, target); bpatel@766: } bpatel@766: return anchor; bpatel@766: } bpatel@766: bpatel@766: /** duke@1: * Get the name of the package, this class is in. duke@1: * duke@1: * @param cd ClassDoc. duke@1: */ duke@1: public String getPkgName(ClassDoc cd) { duke@1: String pkgName = cd.containingPackage().name(); duke@1: if (pkgName.length() > 0) { duke@1: pkgName += "."; duke@1: return pkgName; duke@1: } duke@1: return ""; duke@1: } duke@1: bpatel@233: public boolean getMemberDetailsListPrinted() { bpatel@233: return memberDetailsListPrinted; bpatel@233: } bpatel@233: bpatel@233: /** duke@1: * Print the frameset version of the Html file header. duke@1: * Called only when generating an HTML frameset file. duke@1: * bpatel@766: * @param title Title of this HTML document bpatel@766: * @param noTimeStamp If true, don't print time stamp in header bpatel@766: * @param frameset the frameset to be added to the HTML document duke@1: */ bpatel@766: public void printFramesetDocument(String title, boolean noTimeStamp, jjg@1364: Content frameset) throws IOException { jjg@1410: Content htmlDocType = DocType.FRAMESET; bpatel@766: Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); bpatel@766: Content head = new HtmlTree(HtmlTag.HEAD); jjg@2006: head.addContent(getGeneratedBy(!noTimeStamp)); duke@1: if (configuration.charset.length() > 0) { bpatel@1981: Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, bpatel@766: configuration.charset); bpatel@766: head.addContent(meta); duke@1: } bpatel@766: Content windowTitle = HtmlTree.TITLE(new StringContent(title)); bpatel@766: head.addContent(windowTitle); bpatel@766: head.addContent(getFramesetJavaScript()); bpatel@766: Content htmlTree = HtmlTree.HTML(configuration.getLocale().getLanguage(), bpatel@766: head, frameset); bpatel@766: Content htmlDocument = new HtmlDocument(htmlDocType, bpatel@766: htmlComment, htmlTree); jjg@1365: write(htmlDocument); duke@1: } duke@1: jjg@2006: protected Comment getGeneratedBy(boolean timestamp) { jjg@2006: String text = "Generated by javadoc"; // marker string, deliberately not localized jjg@2006: if (timestamp) { jjg@2006: Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); jjg@2006: Date today = calendar.getTime(); jjg@2006: text += " ("+ ConfigurationImpl.BUILD_DATE + ") on " + today; jjg@2006: } jjg@2006: return new Comment(text); duke@1: } duke@1: }