1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,869 @@ 1.4 +/* 1.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.doclets.formats.html.markup; 1.30 + 1.31 +import java.io.IOException; 1.32 +import java.io.Writer; 1.33 +import java.util.*; 1.34 +import java.nio.charset.*; 1.35 + 1.36 +import com.sun.tools.doclets.internal.toolkit.Content; 1.37 +import com.sun.tools.doclets.internal.toolkit.util.*; 1.38 + 1.39 +/** 1.40 + * Class for generating HTML tree for javadoc output. 1.41 + * 1.42 + * <p><b>This is NOT part of any supported API. 1.43 + * If you write code that depends on this, you do so at your own risk. 1.44 + * This code and its internal interfaces are subject to change or 1.45 + * deletion without notice.</b> 1.46 + * 1.47 + * @author Bhavesh Patel 1.48 + */ 1.49 +public class HtmlTree extends Content { 1.50 + 1.51 + private HtmlTag htmlTag; 1.52 + private Map<HtmlAttr,String> attrs = Collections.<HtmlAttr,String>emptyMap(); 1.53 + private List<Content> content = Collections.<Content>emptyList(); 1.54 + public static final Content EMPTY = new StringContent(""); 1.55 + 1.56 + /** 1.57 + * Constructor to construct HtmlTree object. 1.58 + * 1.59 + * @param tag HTML tag for the HtmlTree object 1.60 + */ 1.61 + public HtmlTree(HtmlTag tag) { 1.62 + htmlTag = nullCheck(tag); 1.63 + } 1.64 + 1.65 + /** 1.66 + * Constructor to construct HtmlTree object. 1.67 + * 1.68 + * @param tag HTML tag for the HtmlTree object 1.69 + * @param contents contents to be added to the tree 1.70 + */ 1.71 + public HtmlTree(HtmlTag tag, Content... contents) { 1.72 + this(tag); 1.73 + for (Content content: contents) 1.74 + addContent(content); 1.75 + } 1.76 + 1.77 + /** 1.78 + * Adds an attribute for the HTML tag. 1.79 + * 1.80 + * @param attrName name of the attribute 1.81 + * @param attrValue value of the attribute 1.82 + */ 1.83 + public void addAttr(HtmlAttr attrName, String attrValue) { 1.84 + if (attrs.isEmpty()) 1.85 + attrs = new LinkedHashMap<HtmlAttr,String>(3); 1.86 + attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue)); 1.87 + } 1.88 + 1.89 + public void setTitle(Content body) { 1.90 + addAttr(HtmlAttr.TITLE, stripHtml(body)); 1.91 + } 1.92 + 1.93 + /** 1.94 + * Adds a style for the HTML tag. 1.95 + * 1.96 + * @param style style to be added 1.97 + */ 1.98 + public void addStyle(HtmlStyle style) { 1.99 + addAttr(HtmlAttr.CLASS, style.toString()); 1.100 + } 1.101 + 1.102 + /** 1.103 + * Adds content for the HTML tag. 1.104 + * 1.105 + * @param tagContent tag content to be added 1.106 + */ 1.107 + public void addContent(Content tagContent) { 1.108 + if (tagContent instanceof ContentBuilder) { 1.109 + for (Content content: ((ContentBuilder)tagContent).contents) { 1.110 + addContent(content); 1.111 + } 1.112 + } 1.113 + else if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) { 1.114 + if (content.isEmpty()) 1.115 + content = new ArrayList<Content>(); 1.116 + content.add(tagContent); 1.117 + } 1.118 + } 1.119 + 1.120 + /** 1.121 + * This method adds a string content to the htmltree. If the last content member 1.122 + * added is a StringContent, append the string to that StringContent or else 1.123 + * create a new StringContent and add it to the html tree. 1.124 + * 1.125 + * @param stringContent string content that needs to be added 1.126 + */ 1.127 + public void addContent(String stringContent) { 1.128 + if (!content.isEmpty()) { 1.129 + Content lastContent = content.get(content.size() - 1); 1.130 + if (lastContent instanceof StringContent) 1.131 + lastContent.addContent(stringContent); 1.132 + else 1.133 + addContent(new StringContent(stringContent)); 1.134 + } 1.135 + else 1.136 + addContent(new StringContent(stringContent)); 1.137 + } 1.138 + 1.139 + public int charCount() { 1.140 + int n = 0; 1.141 + for (Content c : content) 1.142 + n += c.charCount(); 1.143 + return n; 1.144 + } 1.145 + 1.146 + /** 1.147 + * Given a string, escape all special html characters and 1.148 + * return the result. 1.149 + * 1.150 + * @param s The string to check. 1.151 + * @return the original string with all of the HTML characters escaped. 1.152 + */ 1.153 + private static String escapeHtmlChars(String s) { 1.154 + for (int i = 0; i < s.length(); i++) { 1.155 + char ch = s.charAt(i); 1.156 + switch (ch) { 1.157 + // only start building a new string if we need to 1.158 + case '<': case '>': case '&': 1.159 + StringBuilder sb = new StringBuilder(s.substring(0, i)); 1.160 + for ( ; i < s.length(); i++) { 1.161 + ch = s.charAt(i); 1.162 + switch (ch) { 1.163 + case '<': sb.append("<"); break; 1.164 + case '>': sb.append(">"); break; 1.165 + case '&': sb.append("&"); break; 1.166 + default: sb.append(ch); break; 1.167 + } 1.168 + } 1.169 + return sb.toString(); 1.170 + } 1.171 + } 1.172 + return s; 1.173 + } 1.174 + 1.175 + /** 1.176 + * A set of ASCII URI characters to be left unencoded. 1.177 + */ 1.178 + public static final BitSet NONENCODING_CHARS = new BitSet(256); 1.179 + 1.180 + static { 1.181 + // alphabetic characters 1.182 + for (int i = 'a'; i <= 'z'; i++) { 1.183 + NONENCODING_CHARS.set(i); 1.184 + } 1.185 + for (int i = 'A'; i <= 'Z'; i++) { 1.186 + NONENCODING_CHARS.set(i); 1.187 + } 1.188 + // numeric characters 1.189 + for (int i = '0'; i <= '9'; i++) { 1.190 + NONENCODING_CHARS.set(i); 1.191 + } 1.192 + // Reserved characters as per RFC 3986. These are set of delimiting characters. 1.193 + String noEnc = ":/?#[]@!$&'()*+,;="; 1.194 + // Unreserved characters as per RFC 3986 which should not be percent encoded. 1.195 + noEnc += "-._~"; 1.196 + for (int i = 0; i < noEnc.length(); i++) { 1.197 + NONENCODING_CHARS.set(noEnc.charAt(i)); 1.198 + } 1.199 + } 1.200 + 1.201 + private static String encodeURL(String url) { 1.202 + byte[] urlBytes = url.getBytes(Charset.forName("UTF-8")); 1.203 + StringBuilder sb = new StringBuilder(); 1.204 + for (int i = 0; i < urlBytes.length; i++) { 1.205 + int c = urlBytes[i]; 1.206 + if (NONENCODING_CHARS.get(c & 0xFF)) { 1.207 + sb.append((char) c); 1.208 + } else { 1.209 + sb.append(String.format("%%%02X", c & 0xFF)); 1.210 + } 1.211 + } 1.212 + return sb.toString(); 1.213 + } 1.214 + 1.215 + /** 1.216 + * Generates an HTML anchor tag. 1.217 + * 1.218 + * @param ref reference url for the anchor tag 1.219 + * @param body content for the anchor tag 1.220 + * @return an HtmlTree object 1.221 + */ 1.222 + public static HtmlTree A(String ref, Content body) { 1.223 + HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body)); 1.224 + htmltree.addAttr(HtmlAttr.HREF, encodeURL(ref)); 1.225 + return htmltree; 1.226 + } 1.227 + 1.228 + /** 1.229 + * Generates an HTML anchor tag with name attribute and content. 1.230 + * 1.231 + * @param name name for the anchor tag 1.232 + * @param body content for the anchor tag 1.233 + * @return an HtmlTree object 1.234 + */ 1.235 + public static HtmlTree A_NAME(String name, Content body) { 1.236 + HtmlTree htmltree = HtmlTree.A_NAME(name); 1.237 + htmltree.addContent(nullCheck(body)); 1.238 + return htmltree; 1.239 + } 1.240 + 1.241 + /** 1.242 + * Generates an HTML anchor tag with name attribute. 1.243 + * 1.244 + * @param name name for the anchor tag 1.245 + * @return an HtmlTree object 1.246 + */ 1.247 + public static HtmlTree A_NAME(String name) { 1.248 + HtmlTree htmltree = new HtmlTree(HtmlTag.A); 1.249 + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); 1.250 + return htmltree; 1.251 + } 1.252 + 1.253 + /** 1.254 + * Generates a CAPTION tag with some content. 1.255 + * 1.256 + * @param body content for the tag 1.257 + * @return an HtmlTree object for the CAPTION tag 1.258 + */ 1.259 + public static HtmlTree CAPTION(Content body) { 1.260 + HtmlTree htmltree = new HtmlTree(HtmlTag.CAPTION, nullCheck(body)); 1.261 + return htmltree; 1.262 + } 1.263 + 1.264 + /** 1.265 + * Generates a CODE tag with some content. 1.266 + * 1.267 + * @param body content for the tag 1.268 + * @return an HtmlTree object for the CODE tag 1.269 + */ 1.270 + public static HtmlTree CODE(Content body) { 1.271 + HtmlTree htmltree = new HtmlTree(HtmlTag.CODE, nullCheck(body)); 1.272 + return htmltree; 1.273 + } 1.274 + 1.275 + /** 1.276 + * Generates a DD tag with some content. 1.277 + * 1.278 + * @param body content for the tag 1.279 + * @return an HtmlTree object for the DD tag 1.280 + */ 1.281 + public static HtmlTree DD(Content body) { 1.282 + HtmlTree htmltree = new HtmlTree(HtmlTag.DD, nullCheck(body)); 1.283 + return htmltree; 1.284 + } 1.285 + 1.286 + /** 1.287 + * Generates a DL tag with some content. 1.288 + * 1.289 + * @param body content for the tag 1.290 + * @return an HtmlTree object for the DL tag 1.291 + */ 1.292 + public static HtmlTree DL(Content body) { 1.293 + HtmlTree htmltree = new HtmlTree(HtmlTag.DL, nullCheck(body)); 1.294 + return htmltree; 1.295 + } 1.296 + 1.297 + /** 1.298 + * Generates a DIV tag with the style class attributes. It also encloses 1.299 + * a content. 1.300 + * 1.301 + * @param styleClass stylesheet class for the tag 1.302 + * @param body content for the tag 1.303 + * @return an HtmlTree object for the DIV tag 1.304 + */ 1.305 + public static HtmlTree DIV(HtmlStyle styleClass, Content body) { 1.306 + HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body)); 1.307 + if (styleClass != null) 1.308 + htmltree.addStyle(styleClass); 1.309 + return htmltree; 1.310 + } 1.311 + 1.312 + /** 1.313 + * Generates a DIV tag with some content. 1.314 + * 1.315 + * @param body content for the tag 1.316 + * @return an HtmlTree object for the DIV tag 1.317 + */ 1.318 + public static HtmlTree DIV(Content body) { 1.319 + return DIV(null, body); 1.320 + } 1.321 + 1.322 + /** 1.323 + * Generates a DT tag with some content. 1.324 + * 1.325 + * @param body content for the tag 1.326 + * @return an HtmlTree object for the DT tag 1.327 + */ 1.328 + public static HtmlTree DT(Content body) { 1.329 + HtmlTree htmltree = new HtmlTree(HtmlTag.DT, nullCheck(body)); 1.330 + return htmltree; 1.331 + } 1.332 + 1.333 + /** 1.334 + * Generates a FRAME tag. 1.335 + * 1.336 + * @param src the url of the document to be shown in the frame 1.337 + * @param name specifies the name of the frame 1.338 + * @param title the title for the frame 1.339 + * @param scrolling specifies whether to display scrollbars in the frame 1.340 + * @return an HtmlTree object for the FRAME tag 1.341 + */ 1.342 + public static HtmlTree FRAME(String src, String name, String title, String scrolling) { 1.343 + HtmlTree htmltree = new HtmlTree(HtmlTag.FRAME); 1.344 + htmltree.addAttr(HtmlAttr.SRC, nullCheck(src)); 1.345 + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); 1.346 + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); 1.347 + if (scrolling != null) 1.348 + htmltree.addAttr(HtmlAttr.SCROLLING, scrolling); 1.349 + return htmltree; 1.350 + } 1.351 + 1.352 + /** 1.353 + * Generates a Frame tag. 1.354 + * 1.355 + * @param src the url of the document to be shown in the frame 1.356 + * @param name specifies the name of the frame 1.357 + * @param title the title for the frame 1.358 + * @return an HtmlTree object for the SPAN tag 1.359 + */ 1.360 + public static HtmlTree FRAME(String src, String name, String title) { 1.361 + return FRAME(src, name, title, null); 1.362 + } 1.363 + 1.364 + /** 1.365 + * Generates a FRAMESET tag. 1.366 + * 1.367 + * @param cols the size of columns in the frameset 1.368 + * @param rows the size of rows in the frameset 1.369 + * @param title the title for the frameset 1.370 + * @param onload the script to run when the document loads 1.371 + * @return an HtmlTree object for the FRAMESET tag 1.372 + */ 1.373 + public static HtmlTree FRAMESET(String cols, String rows, String title, String onload) { 1.374 + HtmlTree htmltree = new HtmlTree(HtmlTag.FRAMESET); 1.375 + if (cols != null) 1.376 + htmltree.addAttr(HtmlAttr.COLS, cols); 1.377 + if (rows != null) 1.378 + htmltree.addAttr(HtmlAttr.ROWS, rows); 1.379 + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); 1.380 + htmltree.addAttr(HtmlAttr.ONLOAD, nullCheck(onload)); 1.381 + return htmltree; 1.382 + } 1.383 + 1.384 + /** 1.385 + * Generates a heading tag (h1 to h6) with the title and style class attributes. It also encloses 1.386 + * a content. 1.387 + * 1.388 + * @param headingTag the heading tag to be generated 1.389 + * @param printTitle true if title for the tag needs to be printed else false 1.390 + * @param styleClass stylesheet class for the tag 1.391 + * @param body content for the tag 1.392 + * @return an HtmlTree object for the tag 1.393 + */ 1.394 + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, 1.395 + HtmlStyle styleClass, Content body) { 1.396 + HtmlTree htmltree = new HtmlTree(headingTag, nullCheck(body)); 1.397 + if (printTitle) 1.398 + htmltree.setTitle(body); 1.399 + if (styleClass != null) 1.400 + htmltree.addStyle(styleClass); 1.401 + return htmltree; 1.402 + } 1.403 + 1.404 + /** 1.405 + * Generates a heading tag (h1 to h6) with style class attribute. It also encloses 1.406 + * a content. 1.407 + * 1.408 + * @param headingTag the heading tag to be generated 1.409 + * @param styleClass stylesheet class for the tag 1.410 + * @param body content for the tag 1.411 + * @return an HtmlTree object for the tag 1.412 + */ 1.413 + public static HtmlTree HEADING(HtmlTag headingTag, HtmlStyle styleClass, Content body) { 1.414 + return HEADING(headingTag, false, styleClass, body); 1.415 + } 1.416 + 1.417 + /** 1.418 + * Generates a heading tag (h1 to h6) with the title attribute. It also encloses 1.419 + * a content. 1.420 + * 1.421 + * @param headingTag the heading tag to be generated 1.422 + * @param printTitle true if the title for the tag needs to be printed else false 1.423 + * @param body content for the tag 1.424 + * @return an HtmlTree object for the tag 1.425 + */ 1.426 + public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, Content body) { 1.427 + return HEADING(headingTag, printTitle, null, body); 1.428 + } 1.429 + 1.430 + /** 1.431 + * Generates a heading tag (h1 to h6) with some content. 1.432 + * 1.433 + * @param headingTag the heading tag to be generated 1.434 + * @param body content for the tag 1.435 + * @return an HtmlTree object for the tag 1.436 + */ 1.437 + public static HtmlTree HEADING(HtmlTag headingTag, Content body) { 1.438 + return HEADING(headingTag, false, null, body); 1.439 + } 1.440 + 1.441 + /** 1.442 + * Generates an HTML tag with lang attribute. It also adds head and body 1.443 + * content to the HTML tree. 1.444 + * 1.445 + * @param lang language for the HTML document 1.446 + * @param head head for the HTML tag 1.447 + * @param body body for the HTML tag 1.448 + * @return an HtmlTree object for the HTML tag 1.449 + */ 1.450 + public static HtmlTree HTML(String lang, Content head, Content body) { 1.451 + HtmlTree htmltree = new HtmlTree(HtmlTag.HTML, nullCheck(head), nullCheck(body)); 1.452 + htmltree.addAttr(HtmlAttr.LANG, nullCheck(lang)); 1.453 + return htmltree; 1.454 + } 1.455 + 1.456 + /** 1.457 + * Generates a LI tag with some content. 1.458 + * 1.459 + * @param body content for the tag 1.460 + * @return an HtmlTree object for the LI tag 1.461 + */ 1.462 + public static HtmlTree LI(Content body) { 1.463 + return LI(null, body); 1.464 + } 1.465 + 1.466 + /** 1.467 + * Generates a LI tag with some content. 1.468 + * 1.469 + * @param styleClass style for the tag 1.470 + * @param body content for the tag 1.471 + * @return an HtmlTree object for the LI tag 1.472 + */ 1.473 + public static HtmlTree LI(HtmlStyle styleClass, Content body) { 1.474 + HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body)); 1.475 + if (styleClass != null) 1.476 + htmltree.addStyle(styleClass); 1.477 + return htmltree; 1.478 + } 1.479 + 1.480 + /** 1.481 + * Generates a LINK tag with the rel, type, href and title attributes. 1.482 + * 1.483 + * @param rel relevance of the link 1.484 + * @param type type of link 1.485 + * @param href the path for the link 1.486 + * @param title title for the link 1.487 + * @return an HtmlTree object for the LINK tag 1.488 + */ 1.489 + public static HtmlTree LINK(String rel, String type, String href, String title) { 1.490 + HtmlTree htmltree = new HtmlTree(HtmlTag.LINK); 1.491 + htmltree.addAttr(HtmlAttr.REL, nullCheck(rel)); 1.492 + htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type)); 1.493 + htmltree.addAttr(HtmlAttr.HREF, nullCheck(href)); 1.494 + htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title)); 1.495 + return htmltree; 1.496 + } 1.497 + 1.498 + /** 1.499 + * Generates a META tag with the http-equiv, content and charset attributes. 1.500 + * 1.501 + * @param httpEquiv http equiv attribute for the META tag 1.502 + * @param content type of content 1.503 + * @param charSet character set used 1.504 + * @return an HtmlTree object for the META tag 1.505 + */ 1.506 + public static HtmlTree META(String httpEquiv, String content, String charSet) { 1.507 + HtmlTree htmltree = new HtmlTree(HtmlTag.META); 1.508 + String contentCharset = content + "; charset=" + charSet; 1.509 + htmltree.addAttr(HtmlAttr.HTTP_EQUIV, nullCheck(httpEquiv)); 1.510 + htmltree.addAttr(HtmlAttr.CONTENT, contentCharset); 1.511 + return htmltree; 1.512 + } 1.513 + 1.514 + /** 1.515 + * Generates a META tag with the name and content attributes. 1.516 + * 1.517 + * @param name name attribute 1.518 + * @param content type of content 1.519 + * @return an HtmlTree object for the META tag 1.520 + */ 1.521 + public static HtmlTree META(String name, String content) { 1.522 + HtmlTree htmltree = new HtmlTree(HtmlTag.META); 1.523 + htmltree.addAttr(HtmlAttr.NAME, nullCheck(name)); 1.524 + htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content)); 1.525 + return htmltree; 1.526 + } 1.527 + 1.528 + /** 1.529 + * Generates a NOSCRIPT tag with some content. 1.530 + * 1.531 + * @param body content of the noscript tag 1.532 + * @return an HtmlTree object for the NOSCRIPT tag 1.533 + */ 1.534 + public static HtmlTree NOSCRIPT(Content body) { 1.535 + HtmlTree htmltree = new HtmlTree(HtmlTag.NOSCRIPT, nullCheck(body)); 1.536 + return htmltree; 1.537 + } 1.538 + 1.539 + /** 1.540 + * Generates a P tag with some content. 1.541 + * 1.542 + * @param body content of the Paragraph tag 1.543 + * @return an HtmlTree object for the P tag 1.544 + */ 1.545 + public static HtmlTree P(Content body) { 1.546 + return P(null, body); 1.547 + } 1.548 + 1.549 + /** 1.550 + * Generates a P tag with some content. 1.551 + * 1.552 + * @param styleClass style of the Paragraph tag 1.553 + * @param body content of the Paragraph tag 1.554 + * @return an HtmlTree object for the P tag 1.555 + */ 1.556 + public static HtmlTree P(HtmlStyle styleClass, Content body) { 1.557 + HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body)); 1.558 + if (styleClass != null) 1.559 + htmltree.addStyle(styleClass); 1.560 + return htmltree; 1.561 + } 1.562 + 1.563 + /** 1.564 + * Generates a SCRIPT tag with the type and src attributes. 1.565 + * 1.566 + * @param type type of link 1.567 + * @param src the path for the script 1.568 + * @return an HtmlTree object for the SCRIPT tag 1.569 + */ 1.570 + public static HtmlTree SCRIPT(String type, String src) { 1.571 + HtmlTree htmltree = new HtmlTree(HtmlTag.SCRIPT); 1.572 + htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type)); 1.573 + htmltree.addAttr(HtmlAttr.SRC, nullCheck(src)); 1.574 + return htmltree; 1.575 + } 1.576 + 1.577 + /** 1.578 + * Generates a SMALL tag with some content. 1.579 + * 1.580 + * @param body content for the tag 1.581 + * @return an HtmlTree object for the SMALL tag 1.582 + */ 1.583 + public static HtmlTree SMALL(Content body) { 1.584 + HtmlTree htmltree = new HtmlTree(HtmlTag.SMALL, nullCheck(body)); 1.585 + return htmltree; 1.586 + } 1.587 + 1.588 + /** 1.589 + * Generates a SPAN tag with some content. 1.590 + * 1.591 + * @param body content for the tag 1.592 + * @return an HtmlTree object for the SPAN tag 1.593 + */ 1.594 + public static HtmlTree SPAN(Content body) { 1.595 + return SPAN(null, body); 1.596 + } 1.597 + 1.598 + /** 1.599 + * Generates a SPAN tag with style class attribute and some content. 1.600 + * 1.601 + * @param styleClass style class for the tag 1.602 + * @param body content for the tag 1.603 + * @return an HtmlTree object for the SPAN tag 1.604 + */ 1.605 + public static HtmlTree SPAN(HtmlStyle styleClass, Content body) { 1.606 + HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body)); 1.607 + if (styleClass != null) 1.608 + htmltree.addStyle(styleClass); 1.609 + return htmltree; 1.610 + } 1.611 + 1.612 + /** 1.613 + * Generates a SPAN tag with id and style class attributes. It also encloses 1.614 + * a content. 1.615 + * 1.616 + * @param id the id for the tag 1.617 + * @param styleClass stylesheet class for the tag 1.618 + * @param body content for the tag 1.619 + * @return an HtmlTree object for the SPAN tag 1.620 + */ 1.621 + public static HtmlTree SPAN(String id, HtmlStyle styleClass, Content body) { 1.622 + HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body)); 1.623 + htmltree.addAttr(HtmlAttr.ID, nullCheck(id)); 1.624 + if (styleClass != null) 1.625 + htmltree.addStyle(styleClass); 1.626 + return htmltree; 1.627 + } 1.628 + 1.629 + /** 1.630 + * Generates a Table tag with style class, border, cell padding, 1.631 + * cellspacing and summary attributes and some content. 1.632 + * 1.633 + * @param styleClass style of the table 1.634 + * @param border border for the table 1.635 + * @param cellPadding cell padding for the table 1.636 + * @param cellSpacing cell spacing for the table 1.637 + * @param summary summary for the table 1.638 + * @param body content for the table 1.639 + * @return an HtmlTree object for the TABLE tag 1.640 + */ 1.641 + public static HtmlTree TABLE(HtmlStyle styleClass, int border, int cellPadding, 1.642 + int cellSpacing, String summary, Content body) { 1.643 + HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body)); 1.644 + if (styleClass != null) 1.645 + htmltree.addStyle(styleClass); 1.646 + htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border)); 1.647 + htmltree.addAttr(HtmlAttr.CELLPADDING, Integer.toString(cellPadding)); 1.648 + htmltree.addAttr(HtmlAttr.CELLSPACING, Integer.toString(cellSpacing)); 1.649 + htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary)); 1.650 + return htmltree; 1.651 + } 1.652 + 1.653 + /** 1.654 + * Generates a TD tag with style class attribute and some content. 1.655 + * 1.656 + * @param styleClass style for the tag 1.657 + * @param body content for the tag 1.658 + * @return an HtmlTree object for the TD tag 1.659 + */ 1.660 + public static HtmlTree TD(HtmlStyle styleClass, Content body) { 1.661 + HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body)); 1.662 + if (styleClass != null) 1.663 + htmltree.addStyle(styleClass); 1.664 + return htmltree; 1.665 + } 1.666 + 1.667 + /** 1.668 + * Generates a TD tag for an HTML table with some content. 1.669 + * 1.670 + * @param body content for the tag 1.671 + * @return an HtmlTree object for the TD tag 1.672 + */ 1.673 + public static HtmlTree TD(Content body) { 1.674 + return TD(null, body); 1.675 + } 1.676 + 1.677 + /** 1.678 + * Generates a TH tag with style class and scope attributes and some content. 1.679 + * 1.680 + * @param styleClass style for the tag 1.681 + * @param scope scope of the tag 1.682 + * @param body content for the tag 1.683 + * @return an HtmlTree object for the TH tag 1.684 + */ 1.685 + public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) { 1.686 + HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body)); 1.687 + if (styleClass != null) 1.688 + htmltree.addStyle(styleClass); 1.689 + htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope)); 1.690 + return htmltree; 1.691 + } 1.692 + 1.693 + /** 1.694 + * Generates a TH tag with scope attribute and some content. 1.695 + * 1.696 + * @param scope scope of the tag 1.697 + * @param body content for the tag 1.698 + * @return an HtmlTree object for the TH tag 1.699 + */ 1.700 + public static HtmlTree TH(String scope, Content body) { 1.701 + return TH(null, scope, body); 1.702 + } 1.703 + 1.704 + /** 1.705 + * Generates a TITLE tag with some content. 1.706 + * 1.707 + * @param body content for the tag 1.708 + * @return an HtmlTree object for the TITLE tag 1.709 + */ 1.710 + public static HtmlTree TITLE(Content body) { 1.711 + HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body)); 1.712 + return htmltree; 1.713 + } 1.714 + 1.715 + /** 1.716 + * Generates a TR tag for an HTML table with some content. 1.717 + * 1.718 + * @param body content for the tag 1.719 + * @return an HtmlTree object for the TR tag 1.720 + */ 1.721 + public static HtmlTree TR(Content body) { 1.722 + HtmlTree htmltree = new HtmlTree(HtmlTag.TR, nullCheck(body)); 1.723 + return htmltree; 1.724 + } 1.725 + 1.726 + /** 1.727 + * Generates a UL tag with the style class attribute and some content. 1.728 + * 1.729 + * @param styleClass style for the tag 1.730 + * @param body content for the tag 1.731 + * @return an HtmlTree object for the UL tag 1.732 + */ 1.733 + public static HtmlTree UL(HtmlStyle styleClass, Content body) { 1.734 + HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body)); 1.735 + htmltree.addStyle(nullCheck(styleClass)); 1.736 + return htmltree; 1.737 + } 1.738 + 1.739 + /** 1.740 + * {@inheritDoc} 1.741 + */ 1.742 + public boolean isEmpty() { 1.743 + return (!hasContent() && !hasAttrs()); 1.744 + } 1.745 + 1.746 + /** 1.747 + * Returns true if the HTML tree has content. 1.748 + * 1.749 + * @return true if the HTML tree has content else return false 1.750 + */ 1.751 + public boolean hasContent() { 1.752 + return (!content.isEmpty()); 1.753 + } 1.754 + 1.755 + /** 1.756 + * Returns true if the HTML tree has attributes. 1.757 + * 1.758 + * @return true if the HTML tree has attributes else return false 1.759 + */ 1.760 + public boolean hasAttrs() { 1.761 + return (!attrs.isEmpty()); 1.762 + } 1.763 + 1.764 + /** 1.765 + * Returns true if the HTML tree has a specific attribute. 1.766 + * 1.767 + * @param attrName name of the attribute to check within the HTML tree 1.768 + * @return true if the HTML tree has the specified attribute else return false 1.769 + */ 1.770 + public boolean hasAttr(HtmlAttr attrName) { 1.771 + return (attrs.containsKey(attrName)); 1.772 + } 1.773 + 1.774 + /** 1.775 + * Returns true if the HTML tree is valid. This check is more specific to 1.776 + * standard doclet and not exactly similar to W3C specifications. But it 1.777 + * ensures HTML validation. 1.778 + * 1.779 + * @return true if the HTML tree is valid 1.780 + */ 1.781 + public boolean isValid() { 1.782 + switch (htmlTag) { 1.783 + case A : 1.784 + return (hasAttr(HtmlAttr.NAME) || (hasAttr(HtmlAttr.HREF) && hasContent())); 1.785 + case BR : 1.786 + return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR))); 1.787 + case FRAME : 1.788 + return (hasAttr(HtmlAttr.SRC) && !hasContent()); 1.789 + case HR : 1.790 + return (!hasContent()); 1.791 + case IMG : 1.792 + return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent()); 1.793 + case LINK : 1.794 + return (hasAttr(HtmlAttr.HREF) && !hasContent()); 1.795 + case META : 1.796 + return (hasAttr(HtmlAttr.CONTENT) && !hasContent()); 1.797 + case SCRIPT : 1.798 + return ((hasAttr(HtmlAttr.TYPE) && hasAttr(HtmlAttr.SRC) && !hasContent()) || 1.799 + (hasAttr(HtmlAttr.TYPE) && hasContent())); 1.800 + default : 1.801 + return hasContent(); 1.802 + } 1.803 + } 1.804 + 1.805 + /** 1.806 + * Returns true if the element is an inline element. 1.807 + * 1.808 + * @return true if the HTML tag is an inline element 1.809 + */ 1.810 + public boolean isInline() { 1.811 + return (htmlTag.blockType == HtmlTag.BlockType.INLINE); 1.812 + } 1.813 + 1.814 + /** 1.815 + * {@inheritDoc} 1.816 + */ 1.817 + @Override 1.818 + public boolean write(Writer out, boolean atNewline) throws IOException { 1.819 + if (!isInline() && !atNewline) 1.820 + out.write(DocletConstants.NL); 1.821 + String tagString = htmlTag.toString(); 1.822 + out.write("<"); 1.823 + out.write(tagString); 1.824 + Iterator<HtmlAttr> iterator = attrs.keySet().iterator(); 1.825 + HtmlAttr key; 1.826 + String value; 1.827 + while (iterator.hasNext()) { 1.828 + key = iterator.next(); 1.829 + value = attrs.get(key); 1.830 + out.write(" "); 1.831 + out.write(key.toString()); 1.832 + if (!value.isEmpty()) { 1.833 + out.write("=\""); 1.834 + out.write(value); 1.835 + out.write("\""); 1.836 + } 1.837 + } 1.838 + out.write(">"); 1.839 + boolean nl = false; 1.840 + for (Content c : content) 1.841 + nl = c.write(out, nl); 1.842 + if (htmlTag.endTagRequired()) { 1.843 + out.write("</"); 1.844 + out.write(tagString); 1.845 + out.write(">"); 1.846 + } 1.847 + if (!isInline()) { 1.848 + out.write(DocletConstants.NL); 1.849 + return true; 1.850 + } else { 1.851 + return false; 1.852 + } 1.853 + } 1.854 + 1.855 + /** 1.856 + * Given a Content node, strips all html characters and 1.857 + * return the result. 1.858 + * 1.859 + * @param body The content node to check. 1.860 + * @return the plain text from the content node 1.861 + * 1.862 + */ 1.863 + private static String stripHtml(Content body) { 1.864 + String rawString = body.toString(); 1.865 + // remove HTML tags 1.866 + rawString = rawString.replaceAll("\\<.*?>", " "); 1.867 + // consolidate multiple spaces between a word to a single space 1.868 + rawString = rawString.replaceAll("\\b\\s{2,}\\b", " "); 1.869 + // remove extra whitespaces 1.870 + return rawString.trim(); 1.871 + } 1.872 +}