src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java

Tue, 20 Aug 2013 14:55:20 -0700

author
jjg
date
Tue, 20 Aug 2013 14:55:20 -0700
changeset 1964
79e341614c50
parent 1936
33294f02c9a5
child 1981
7fb27bc201cc
permissions
-rw-r--r--

8022080: javadoc generates invalid HTML in Turkish locale
Reviewed-by: bpatel

     1 /*
     2  * Copyright (c) 2010, 2013, 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  */
    26 package com.sun.tools.doclets.formats.html.markup;
    28 import java.io.IOException;
    29 import java.io.Writer;
    30 import java.util.*;
    32 import com.sun.tools.doclets.internal.toolkit.Content;
    33 import com.sun.tools.doclets.internal.toolkit.util.*;
    35 /**
    36  * Class for generating HTML tree for javadoc output.
    37  *
    38  *  <p><b>This is NOT part of any supported API.
    39  *  If you write code that depends on this, you do so at your own risk.
    40  *  This code and its internal interfaces are subject to change or
    41  *  deletion without notice.</b>
    42  *
    43  * @author Bhavesh Patel
    44  */
    45 public class HtmlTree extends Content {
    47     private HtmlTag htmlTag;
    48     private Map<HtmlAttr,String> attrs = Collections.<HtmlAttr,String>emptyMap();
    49     private List<Content> content = Collections.<Content>emptyList();
    50     public static final Content EMPTY = new StringContent("");
    52     /**
    53      * Constructor to construct HtmlTree object.
    54      *
    55      * @param tag HTML tag for the HtmlTree object
    56      */
    57     public HtmlTree(HtmlTag tag) {
    58         htmlTag = nullCheck(tag);
    59     }
    61     /**
    62      * Constructor to construct HtmlTree object.
    63      *
    64      * @param tag HTML tag for the HtmlTree object
    65      * @param contents contents to be added to the tree
    66      */
    67     public HtmlTree(HtmlTag tag, Content... contents) {
    68         this(tag);
    69         for (Content content: contents)
    70             addContent(content);
    71     }
    73     /**
    74      * Adds an attribute for the HTML tag.
    75      *
    76      * @param attrName name of the attribute
    77      * @param attrValue value of the attribute
    78      */
    79     public void addAttr(HtmlAttr attrName, String attrValue) {
    80         if (attrs.isEmpty())
    81             attrs = new LinkedHashMap<HtmlAttr,String>(3);
    82         attrs.put(nullCheck(attrName), escapeHtmlChars(attrValue));
    83     }
    85     public void setTitle(Content body) {
    86         addAttr(HtmlAttr.TITLE, stripHtml(body));
    87     }
    89     /**
    90      * Adds a style for the HTML tag.
    91      *
    92      * @param style style to be added
    93      */
    94     public void addStyle(HtmlStyle style) {
    95         addAttr(HtmlAttr.CLASS, style.toString());
    96     }
    98     /**
    99      * Adds content for the HTML tag.
   100      *
   101      * @param tagContent tag content to be added
   102      */
   103     public void addContent(Content tagContent) {
   104         if (tagContent == HtmlTree.EMPTY || tagContent.isValid()) {
   105             if (content.isEmpty())
   106                 content = new ArrayList<Content>();
   107             content.add(tagContent);
   108         }
   109     }
   111     /**
   112      * This method adds a string content to the htmltree. If the last content member
   113      * added is a StringContent, append the string to that StringContent or else
   114      * create a new StringContent and add it to the html tree.
   115      *
   116      * @param stringContent string content that needs to be added
   117      */
   118     public void addContent(String stringContent) {
   119         if (!content.isEmpty()) {
   120             Content lastContent = content.get(content.size() - 1);
   121             if (lastContent instanceof StringContent)
   122                 lastContent.addContent(stringContent);
   123             else
   124                 addContent(new StringContent(stringContent));
   125         }
   126         else
   127             addContent(new StringContent(stringContent));
   128     }
   130     public int charCount() {
   131         int n = 0;
   132         for (Content c : content)
   133             n += c.charCount();
   134         return n;
   135     }
   137     /**
   138      * Given a string, escape all special html characters and
   139      * return the result.
   140      *
   141      * @param s The string to check.
   142      * @return the original string with all of the HTML characters escaped.
   143      */
   144     private static String escapeHtmlChars(String s) {
   145         for (int i = 0; i < s.length(); i++) {
   146             char ch = s.charAt(i);
   147             switch (ch) {
   148                 // only start building a new string if we need to
   149                 case '<': case '>': case '&':
   150                     StringBuilder sb = new StringBuilder(s.substring(0, i));
   151                     for ( ; i < s.length(); i++) {
   152                         ch = s.charAt(i);
   153                         switch (ch) {
   154                             case '<': sb.append("&lt;");  break;
   155                             case '>': sb.append("&gt;");  break;
   156                             case '&': sb.append("&amp;"); break;
   157                             default:  sb.append(ch);      break;
   158                         }
   159                     }
   160                     return sb.toString();
   161             }
   162         }
   163         return s;
   164     }
   166     /**
   167      * Generates an HTML anchor tag.
   168      *
   169      * @param ref reference url for the anchor tag
   170      * @param body content for the anchor tag
   171      * @return an HtmlTree object
   172      */
   173     public static HtmlTree A(String ref, Content body) {
   174         HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body));
   175         htmltree.addAttr(HtmlAttr.HREF, ref);
   176         return htmltree;
   177     }
   179     /**
   180      * Generates an HTML anchor tag with name attribute and content.
   181      *
   182      * @param name name for the anchor tag
   183      * @param body content for the anchor tag
   184      * @return an HtmlTree object
   185      */
   186     public static HtmlTree A_NAME(String name, Content body) {
   187         HtmlTree htmltree = HtmlTree.A_NAME(name);
   188         htmltree.addContent(nullCheck(body));
   189         return htmltree;
   190     }
   192     /**
   193      * Generates an HTML anchor tag with name attribute.
   194      *
   195      * @param name name for the anchor tag
   196      * @return an HtmlTree object
   197      */
   198     public static HtmlTree A_NAME(String name) {
   199         HtmlTree htmltree = new HtmlTree(HtmlTag.A);
   200         htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
   201         return htmltree;
   202     }
   204     /**
   205      * Generates a CAPTION tag with some content.
   206      *
   207      * @param body content for the tag
   208      * @return an HtmlTree object for the CAPTION tag
   209      */
   210     public static HtmlTree CAPTION(Content body) {
   211         HtmlTree htmltree = new HtmlTree(HtmlTag.CAPTION, nullCheck(body));
   212         return htmltree;
   213     }
   215     /**
   216      * Generates a CODE tag with some content.
   217      *
   218      * @param body content for the tag
   219      * @return an HtmlTree object for the CODE tag
   220      */
   221     public static HtmlTree CODE(Content body) {
   222         HtmlTree htmltree = new HtmlTree(HtmlTag.CODE, nullCheck(body));
   223         return htmltree;
   224     }
   226     /**
   227      * Generates a DD tag with some content.
   228      *
   229      * @param body content for the tag
   230      * @return an HtmlTree object for the DD tag
   231      */
   232     public static HtmlTree DD(Content body) {
   233         HtmlTree htmltree = new HtmlTree(HtmlTag.DD, nullCheck(body));
   234         return htmltree;
   235     }
   237     /**
   238      * Generates a DL tag with some content.
   239      *
   240      * @param body content for the tag
   241      * @return an HtmlTree object for the DL tag
   242      */
   243     public static HtmlTree DL(Content body) {
   244         HtmlTree htmltree = new HtmlTree(HtmlTag.DL, nullCheck(body));
   245         return htmltree;
   246     }
   248     /**
   249      * Generates a DIV tag with the style class attributes. It also encloses
   250      * a content.
   251      *
   252      * @param styleClass stylesheet class for the tag
   253      * @param body content for the tag
   254      * @return an HtmlTree object for the DIV tag
   255      */
   256     public static HtmlTree DIV(HtmlStyle styleClass, Content body) {
   257         HtmlTree htmltree = new HtmlTree(HtmlTag.DIV, nullCheck(body));
   258         if (styleClass != null)
   259             htmltree.addStyle(styleClass);
   260         return htmltree;
   261     }
   263     /**
   264      * Generates a DIV tag with some content.
   265      *
   266      * @param body content for the tag
   267      * @return an HtmlTree object for the DIV tag
   268      */
   269     public static HtmlTree DIV(Content body) {
   270         return DIV(null, body);
   271     }
   273     /**
   274      * Generates a DT tag with some content.
   275      *
   276      * @param body content for the tag
   277      * @return an HtmlTree object for the DT tag
   278      */
   279     public static HtmlTree DT(Content body) {
   280         HtmlTree htmltree = new HtmlTree(HtmlTag.DT, nullCheck(body));
   281         return htmltree;
   282     }
   284     /**
   285      * Generates a FRAME tag.
   286      *
   287      * @param src the url of the document to be shown in the frame
   288      * @param name specifies the name of the frame
   289      * @param title the title for the frame
   290      * @param scrolling specifies whether to display scrollbars in the frame
   291      * @return an HtmlTree object for the FRAME tag
   292      */
   293     public static HtmlTree FRAME(String src, String name, String title, String scrolling) {
   294         HtmlTree htmltree = new HtmlTree(HtmlTag.FRAME);
   295         htmltree.addAttr(HtmlAttr.SRC, nullCheck(src));
   296         htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
   297         htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
   298         if (scrolling != null)
   299             htmltree.addAttr(HtmlAttr.SCROLLING, scrolling);
   300         return htmltree;
   301     }
   303     /**
   304      * Generates a Frame tag.
   305      *
   306      * @param src the url of the document to be shown in the frame
   307      * @param name specifies the name of the frame
   308      * @param title the title for the frame
   309      * @return an HtmlTree object for the SPAN tag
   310      */
   311     public static HtmlTree FRAME(String src, String name, String title) {
   312         return FRAME(src, name, title, null);
   313     }
   315     /**
   316      * Generates a FRAMESET tag.
   317      *
   318      * @param cols the size of columns in the frameset
   319      * @param rows the size of rows in the frameset
   320      * @param title the title for the frameset
   321      * @param onload the script to run when the document loads
   322      * @return an HtmlTree object for the FRAMESET tag
   323      */
   324     public static HtmlTree FRAMESET(String cols, String rows, String title, String onload) {
   325         HtmlTree htmltree = new HtmlTree(HtmlTag.FRAMESET);
   326         if (cols != null)
   327             htmltree.addAttr(HtmlAttr.COLS, cols);
   328         if (rows != null)
   329             htmltree.addAttr(HtmlAttr.ROWS, rows);
   330         htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
   331         htmltree.addAttr(HtmlAttr.ONLOAD, nullCheck(onload));
   332         return htmltree;
   333     }
   335     /**
   336      * Generates a heading tag (h1 to h6) with the title and style class attributes. It also encloses
   337      * a content.
   338      *
   339      * @param headingTag the heading tag to be generated
   340      * @param printTitle true if title for the tag needs to be printed else false
   341      * @param styleClass stylesheet class for the tag
   342      * @param body content for the tag
   343      * @return an HtmlTree object for the tag
   344      */
   345     public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle,
   346             HtmlStyle styleClass, Content body) {
   347         HtmlTree htmltree = new HtmlTree(headingTag, nullCheck(body));
   348         if (printTitle)
   349             htmltree.setTitle(body);
   350         if (styleClass != null)
   351             htmltree.addStyle(styleClass);
   352         return htmltree;
   353     }
   355     /**
   356      * Generates a heading tag (h1 to h6) with style class attribute. It also encloses
   357      * a content.
   358      *
   359      * @param headingTag the heading tag to be generated
   360      * @param styleClass stylesheet class for the tag
   361      * @param body content for the tag
   362      * @return an HtmlTree object for the tag
   363      */
   364     public static HtmlTree HEADING(HtmlTag headingTag, HtmlStyle styleClass, Content body) {
   365         return HEADING(headingTag, false, styleClass, body);
   366     }
   368     /**
   369      * Generates a heading tag (h1 to h6) with the title attribute. It also encloses
   370      * a content.
   371      *
   372      * @param headingTag the heading tag to be generated
   373      * @param printTitle true if the title for the tag needs to be printed else false
   374      * @param body content for the tag
   375      * @return an HtmlTree object for the tag
   376      */
   377     public static HtmlTree HEADING(HtmlTag headingTag, boolean printTitle, Content body) {
   378         return HEADING(headingTag, printTitle, null, body);
   379     }
   381     /**
   382      * Generates a heading tag (h1 to h6)  with some content.
   383      *
   384      * @param headingTag the heading tag to be generated
   385      * @param body content for the tag
   386      * @return an HtmlTree object for the tag
   387      */
   388     public static HtmlTree HEADING(HtmlTag headingTag, Content body) {
   389         return HEADING(headingTag, false, null, body);
   390     }
   392     /**
   393      * Generates an HTML tag with lang attribute. It also adds head and body
   394      * content to the HTML tree.
   395      *
   396      * @param lang language for the HTML document
   397      * @param head head for the HTML tag
   398      * @param body body for the HTML tag
   399      * @return an HtmlTree object for the HTML tag
   400      */
   401     public static HtmlTree HTML(String lang, Content head, Content body) {
   402         HtmlTree htmltree = new HtmlTree(HtmlTag.HTML, nullCheck(head), nullCheck(body));
   403         htmltree.addAttr(HtmlAttr.LANG, nullCheck(lang));
   404         return htmltree;
   405     }
   407     /**
   408      * Generates a LI tag with some content.
   409      *
   410      * @param body content for the tag
   411      * @return an HtmlTree object for the LI tag
   412      */
   413     public static HtmlTree LI(Content body) {
   414         return LI(null, body);
   415     }
   417     /**
   418      * Generates a LI tag with some content.
   419      *
   420      * @param styleClass style for the tag
   421      * @param body content for the tag
   422      * @return an HtmlTree object for the LI tag
   423      */
   424     public static HtmlTree LI(HtmlStyle styleClass, Content body) {
   425         HtmlTree htmltree = new HtmlTree(HtmlTag.LI, nullCheck(body));
   426         if (styleClass != null)
   427             htmltree.addStyle(styleClass);
   428         return htmltree;
   429     }
   431     /**
   432      * Generates a LINK tag with the rel, type, href and title attributes.
   433      *
   434      * @param rel relevance of the link
   435      * @param type type of link
   436      * @param href the path for the link
   437      * @param title title for the link
   438      * @return an HtmlTree object for the LINK tag
   439      */
   440     public static HtmlTree LINK(String rel, String type, String href, String title) {
   441         HtmlTree htmltree = new HtmlTree(HtmlTag.LINK);
   442         htmltree.addAttr(HtmlAttr.REL, nullCheck(rel));
   443         htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type));
   444         htmltree.addAttr(HtmlAttr.HREF, nullCheck(href));
   445         htmltree.addAttr(HtmlAttr.TITLE, nullCheck(title));
   446         return htmltree;
   447     }
   449     /**
   450      * Generates a META tag with the http-equiv, content and charset attributes.
   451      *
   452      * @param httpEquiv http equiv attribute for the META tag
   453      * @param content type of content
   454      * @param charSet character set used
   455      * @return an HtmlTree object for the META tag
   456      */
   457     public static HtmlTree META(String httpEquiv, String content, String charSet) {
   458         HtmlTree htmltree = new HtmlTree(HtmlTag.META);
   459         htmltree.addAttr(HtmlAttr.HTTP_EQUIV, nullCheck(httpEquiv));
   460         htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content));
   461         htmltree.addAttr(HtmlAttr.CHARSET, nullCheck(charSet));
   462         return htmltree;
   463     }
   465     /**
   466      * Generates a META tag with the name and content attributes.
   467      *
   468      * @param name name attribute
   469      * @param content type of content
   470      * @return an HtmlTree object for the META tag
   471      */
   472     public static HtmlTree META(String name, String content) {
   473         HtmlTree htmltree = new HtmlTree(HtmlTag.META);
   474         htmltree.addAttr(HtmlAttr.NAME, nullCheck(name));
   475         htmltree.addAttr(HtmlAttr.CONTENT, nullCheck(content));
   476         return htmltree;
   477     }
   479     /**
   480      * Generates a NOSCRIPT tag with some content.
   481      *
   482      * @param body content of the noscript tag
   483      * @return an HtmlTree object for the NOSCRIPT tag
   484      */
   485     public static HtmlTree NOSCRIPT(Content body) {
   486         HtmlTree htmltree = new HtmlTree(HtmlTag.NOSCRIPT, nullCheck(body));
   487         return htmltree;
   488     }
   490     /**
   491      * Generates a P tag with some content.
   492      *
   493      * @param body content of the Paragraph tag
   494      * @return an HtmlTree object for the P tag
   495      */
   496     public static HtmlTree P(Content body) {
   497         return P(null, body);
   498     }
   500     /**
   501      * Generates a P tag with some content.
   502      *
   503      * @param styleClass style of the Paragraph tag
   504      * @param body content of the Paragraph tag
   505      * @return an HtmlTree object for the P tag
   506      */
   507     public static HtmlTree P(HtmlStyle styleClass, Content body) {
   508         HtmlTree htmltree = new HtmlTree(HtmlTag.P, nullCheck(body));
   509         if (styleClass != null)
   510             htmltree.addStyle(styleClass);
   511         return htmltree;
   512     }
   514     /**
   515      * Generates a SCRIPT tag with the type and src attributes.
   516      *
   517      * @param type type of link
   518      * @param src the path for the script
   519      * @return an HtmlTree object for the SCRIPT tag
   520      */
   521     public static HtmlTree SCRIPT(String type, String src) {
   522         HtmlTree htmltree = new HtmlTree(HtmlTag.SCRIPT);
   523         htmltree.addAttr(HtmlAttr.TYPE, nullCheck(type));
   524         htmltree.addAttr(HtmlAttr.SRC, nullCheck(src));
   525         return htmltree;
   526     }
   528     /**
   529      * Generates a SMALL tag with some content.
   530      *
   531      * @param body content for the tag
   532      * @return an HtmlTree object for the SMALL tag
   533      */
   534     public static HtmlTree SMALL(Content body) {
   535         HtmlTree htmltree = new HtmlTree(HtmlTag.SMALL, nullCheck(body));
   536         return htmltree;
   537     }
   539     /**
   540      * Generates a SPAN tag with some content.
   541      *
   542      * @param body content for the tag
   543      * @return an HtmlTree object for the SPAN tag
   544      */
   545     public static HtmlTree SPAN(Content body) {
   546         return SPAN(null, body);
   547     }
   549     /**
   550      * Generates a SPAN tag with style class attribute and some content.
   551      *
   552      * @param styleClass style class for the tag
   553      * @param body content for the tag
   554      * @return an HtmlTree object for the SPAN tag
   555      */
   556     public static HtmlTree SPAN(HtmlStyle styleClass, Content body) {
   557         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
   558         if (styleClass != null)
   559             htmltree.addStyle(styleClass);
   560         return htmltree;
   561     }
   563     /**
   564      * Generates a SPAN tag with id and style class attributes. It also encloses
   565      * a content.
   566      *
   567      * @param id the id for the tag
   568      * @param styleClass stylesheet class for the tag
   569      * @param body content for the tag
   570      * @return an HtmlTree object for the SPAN tag
   571      */
   572     public static HtmlTree SPAN(String id, HtmlStyle styleClass, Content body) {
   573         HtmlTree htmltree = new HtmlTree(HtmlTag.SPAN, nullCheck(body));
   574         htmltree.addAttr(HtmlAttr.ID, nullCheck(id));
   575         if (styleClass != null)
   576             htmltree.addStyle(styleClass);
   577         return htmltree;
   578     }
   580     /**
   581      * Generates a Table tag with border, width and summary attributes and
   582      * some content.
   583      *
   584      * @param border border for the table
   585      * @param width width of the table
   586      * @param summary summary for the table
   587      * @param body content for the table
   588      * @return an HtmlTree object for the TABLE tag
   589      */
   590     public static HtmlTree TABLE(int border, int width, String summary,
   591             Content body) {
   592         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
   593         htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border));
   594         htmltree.addAttr(HtmlAttr.WIDTH, Integer.toString(width));
   595         htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
   596         return htmltree;
   597     }
   599     /**
   600      * Generates a Table tag with style class, border, cell padding,
   601      * cellspacing and summary attributes and some content.
   602      *
   603      * @param styleClass style of the table
   604      * @param border border for the table
   605      * @param cellPadding cell padding for the table
   606      * @param cellSpacing cell spacing for the table
   607      * @param summary summary for the table
   608      * @param body content for the table
   609      * @return an HtmlTree object for the TABLE tag
   610      */
   611     public static HtmlTree TABLE(HtmlStyle styleClass, int border, int cellPadding,
   612             int cellSpacing, String summary, Content body) {
   613         HtmlTree htmltree = new HtmlTree(HtmlTag.TABLE, nullCheck(body));
   614         if (styleClass != null)
   615             htmltree.addStyle(styleClass);
   616         htmltree.addAttr(HtmlAttr.BORDER, Integer.toString(border));
   617         htmltree.addAttr(HtmlAttr.CELLPADDING, Integer.toString(cellPadding));
   618         htmltree.addAttr(HtmlAttr.CELLSPACING, Integer.toString(cellSpacing));
   619         htmltree.addAttr(HtmlAttr.SUMMARY, nullCheck(summary));
   620         return htmltree;
   621     }
   623     /**
   624      * Generates a Table tag with border, cell padding,
   625      * cellspacing and summary attributes and some content.
   626      *
   627      * @param border border for the table
   628      * @param cellPadding cell padding for the table
   629      * @param cellSpacing cell spacing for the table
   630      * @param summary summary for the table
   631      * @param body content for the table
   632      * @return an HtmlTree object for the TABLE tag
   633      */
   634     public static HtmlTree TABLE(int border, int cellPadding,
   635             int cellSpacing, String summary, Content body) {
   636         return TABLE(null, border, cellPadding, cellSpacing, summary, body);
   637     }
   639     /**
   640      * Generates a TD tag with style class attribute and some content.
   641      *
   642      * @param styleClass style for the tag
   643      * @param body content for the tag
   644      * @return an HtmlTree object for the TD tag
   645      */
   646     public static HtmlTree TD(HtmlStyle styleClass, Content body) {
   647         HtmlTree htmltree = new HtmlTree(HtmlTag.TD, nullCheck(body));
   648         if (styleClass != null)
   649             htmltree.addStyle(styleClass);
   650         return htmltree;
   651     }
   653     /**
   654      * Generates a TD tag for an HTML table with some content.
   655      *
   656      * @param body content for the tag
   657      * @return an HtmlTree object for the TD tag
   658      */
   659     public static HtmlTree TD(Content body) {
   660         return TD(null, body);
   661     }
   663     /**
   664      * Generates a TH tag with style class and scope attributes and some content.
   665      *
   666      * @param styleClass style for the tag
   667      * @param scope scope of the tag
   668      * @param body content for the tag
   669      * @return an HtmlTree object for the TH tag
   670      */
   671     public static HtmlTree TH(HtmlStyle styleClass, String scope, Content body) {
   672         HtmlTree htmltree = new HtmlTree(HtmlTag.TH, nullCheck(body));
   673         if (styleClass != null)
   674             htmltree.addStyle(styleClass);
   675         htmltree.addAttr(HtmlAttr.SCOPE, nullCheck(scope));
   676         return htmltree;
   677     }
   679     /**
   680      * Generates a TH tag with scope attribute and some content.
   681      *
   682      * @param scope scope of the tag
   683      * @param body content for the tag
   684      * @return an HtmlTree object for the TH tag
   685      */
   686     public static HtmlTree TH(String scope, Content body) {
   687         return TH(null, scope, body);
   688     }
   690     /**
   691      * Generates a TITLE tag with some content.
   692      *
   693      * @param body content for the tag
   694      * @return an HtmlTree object for the TITLE tag
   695      */
   696     public static HtmlTree TITLE(Content body) {
   697         HtmlTree htmltree = new HtmlTree(HtmlTag.TITLE, nullCheck(body));
   698         return htmltree;
   699     }
   701     /**
   702      * Generates a TR tag for an HTML table with some content.
   703      *
   704      * @param body content for the tag
   705      * @return an HtmlTree object for the TR tag
   706      */
   707     public static HtmlTree TR(Content body) {
   708         HtmlTree htmltree = new HtmlTree(HtmlTag.TR, nullCheck(body));
   709         return htmltree;
   710     }
   712     /**
   713      * Generates a UL tag with the style class attribute and some content.
   714      *
   715      * @param styleClass style for the tag
   716      * @param body content for the tag
   717      * @return an HtmlTree object for the UL tag
   718      */
   719     public static HtmlTree UL(HtmlStyle styleClass, Content body) {
   720         HtmlTree htmltree = new HtmlTree(HtmlTag.UL, nullCheck(body));
   721         htmltree.addStyle(nullCheck(styleClass));
   722         return htmltree;
   723     }
   725     /**
   726      * {@inheritDoc}
   727      */
   728     public boolean isEmpty() {
   729         return (!hasContent() && !hasAttrs());
   730     }
   732     /**
   733      * Returns true if the HTML tree has content.
   734      *
   735      * @return true if the HTML tree has content else return false
   736      */
   737     public boolean hasContent() {
   738         return (!content.isEmpty());
   739     }
   741     /**
   742      * Returns true if the HTML tree has attributes.
   743      *
   744      * @return true if the HTML tree has attributes else return false
   745      */
   746     public boolean hasAttrs() {
   747         return (!attrs.isEmpty());
   748     }
   750     /**
   751      * Returns true if the HTML tree has a specific attribute.
   752      *
   753      * @param attrName name of the attribute to check within the HTML tree
   754      * @return true if the HTML tree has the specified attribute else return false
   755      */
   756     public boolean hasAttr(HtmlAttr attrName) {
   757         return (attrs.containsKey(attrName));
   758     }
   760     /**
   761      * Returns true if the HTML tree is valid. This check is more specific to
   762      * standard doclet and not exactly similar to W3C specifications. But it
   763      * ensures HTML validation.
   764      *
   765      * @return true if the HTML tree is valid
   766      */
   767     public boolean isValid() {
   768         switch (htmlTag) {
   769             case A :
   770                 return (hasAttr(HtmlAttr.NAME) || (hasAttr(HtmlAttr.HREF) && hasContent()));
   771             case BR :
   772                 return (!hasContent() && (!hasAttrs() || hasAttr(HtmlAttr.CLEAR)));
   773             case FRAME :
   774                 return (hasAttr(HtmlAttr.SRC) && !hasContent());
   775             case HR :
   776                 return (!hasContent());
   777             case IMG :
   778                 return (hasAttr(HtmlAttr.SRC) && hasAttr(HtmlAttr.ALT) && !hasContent());
   779             case LINK :
   780                 return (hasAttr(HtmlAttr.HREF) && !hasContent());
   781             case META :
   782                 return (hasAttr(HtmlAttr.CONTENT) && !hasContent());
   783             case SCRIPT :
   784                 return ((hasAttr(HtmlAttr.TYPE) && hasAttr(HtmlAttr.SRC) && !hasContent()) ||
   785                         (hasAttr(HtmlAttr.TYPE) && hasContent()));
   786             default :
   787                 return hasContent();
   788         }
   789     }
   791     /**
   792      * Returns true if the element is an inline element.
   793      *
   794      * @return true if the HTML tag is an inline element
   795      */
   796     public boolean isInline() {
   797         return (htmlTag.blockType == HtmlTag.BlockType.INLINE);
   798     }
   800     /**
   801      * {@inheritDoc}
   802      */
   803     @Override
   804     public boolean write(Writer out, boolean atNewline) throws IOException {
   805         if (!isInline() && !atNewline)
   806             out.write(DocletConstants.NL);
   807         String tagString = htmlTag.toString();
   808         out.write("<");
   809         out.write(tagString);
   810         Iterator<HtmlAttr> iterator = attrs.keySet().iterator();
   811         HtmlAttr key;
   812         String value;
   813         while (iterator.hasNext()) {
   814             key = iterator.next();
   815             value = attrs.get(key);
   816             out.write(" ");
   817             out.write(key.toString());
   818             if (!value.isEmpty()) {
   819                 out.write("=\"");
   820                 out.write(value);
   821                 out.write("\"");
   822             }
   823         }
   824         out.write(">");
   825         boolean nl = false;
   826         for (Content c : content)
   827             nl = c.write(out, nl);
   828         if (htmlTag.endTagRequired()) {
   829             out.write("</");
   830             out.write(tagString);
   831             out.write(">");
   832         }
   833         if (!isInline()) {
   834             out.write(DocletConstants.NL);
   835             return true;
   836         } else {
   837             return false;
   838         }
   839     }
   841     /**
   842      * Given a Content node, strips all html characters and
   843      * return the result.
   844      *
   845      * @param body The content node to check.
   846      * @return the plain text from the content node
   847      *
   848      */
   849     private static String stripHtml(Content body) {
   850         String rawString = body.toString();
   851         // remove HTML tags
   852         rawString = rawString.replaceAll("\\<.*?>", " ");
   853         // consolidate multiple spaces between a word to a single space
   854         rawString = rawString.replaceAll("\\b\\s{2,}\\b", " ");
   855         // remove extra whitespaces
   856         return rawString.trim();
   857     }
   858 }

mercurial