src/share/classes/com/sun/tools/doclint/HtmlTag.java

Tue, 17 Dec 2013 10:55:59 +0100

author
jlahoda
date
Tue, 17 Dec 2013 10:55:59 +0100
changeset 2413
fe033d997ddf
parent 2051
96dcb66e6b0a
child 2525
2eb010b6cb22
child 3315
6f0746b6de9f
permissions
-rw-r--r--

8029800: Flags.java uses String.toLowerCase without specifying Locale
Summary: Introducing StringUtils.toLowerCase/toUpperCase independent on the default locale, converting almost all usages of String.toLowerCase/toUpperCase to use the new methods.
Reviewed-by: jjg, 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.doclint;
    28 import java.util.Set;
    29 import java.util.Collections;
    30 import java.util.EnumMap;
    31 import java.util.EnumSet;
    32 import java.util.HashMap;
    33 import java.util.Locale;
    34 import java.util.Map;
    36 import javax.lang.model.element.Name;
    38 import static com.sun.tools.doclint.HtmlTag.Attr.*;
    39 import com.sun.tools.javac.util.StringUtils;
    41 /**
    42  * Enum representing HTML tags.
    43  *
    44  * The intent of this class is to embody the semantics of W3C HTML 4.01
    45  * to the extent supported/used by javadoc.
    46  * In time, we may wish to transition javadoc and doclint to using HTML 5.
    47  *
    48  * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
    49  * Eventually, these two should be merged back together, and possibly made
    50  * public.
    51  *
    52  * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
    53  * @see <a href="http://www.w3.org/TR/html5/">HTML 5 Specification</a>
    54  * @author Bhavesh Patel
    55  * @author Jonathan Gibbons (revised)
    56  */
    57 public enum HtmlTag {
    58     A(BlockType.INLINE, EndKind.REQUIRED,
    59             attrs(AttrKind.OK, HREF, TARGET, NAME)),
    61     B(BlockType.INLINE, EndKind.REQUIRED,
    62             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    64     BIG(BlockType.INLINE, EndKind.REQUIRED,
    65             EnumSet.of(Flag.EXPECT_CONTENT)),
    67     BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
    68             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    70     BODY(BlockType.OTHER, EndKind.REQUIRED),
    72     BR(BlockType.INLINE, EndKind.NONE,
    73             attrs(AttrKind.USE_CSS, CLEAR)),
    75     CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
    76             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    78     CENTER(BlockType.BLOCK, EndKind.REQUIRED,
    79             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    81     CITE(BlockType.INLINE, EndKind.REQUIRED,
    82             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    84     CODE(BlockType.INLINE, EndKind.REQUIRED,
    85             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    87     DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
    88             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    90     DFN(BlockType.INLINE, EndKind.REQUIRED,
    91             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    93     DIV(BlockType.BLOCK, EndKind.REQUIRED,
    94             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    96     DL(BlockType.BLOCK, EndKind.REQUIRED,
    97             EnumSet.of(Flag.EXPECT_CONTENT),
    98             attrs(AttrKind.USE_CSS, COMPACT)) {
    99         @Override
   100         public boolean accepts(HtmlTag t) {
   101             return (t == DT) || (t == DD);
   102         }
   103     },
   105     DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   106             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
   108     EM(BlockType.INLINE, EndKind.REQUIRED,
   109             EnumSet.of(Flag.NO_NEST)),
   111     FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
   112             EnumSet.of(Flag.EXPECT_CONTENT),
   113             attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
   115     FRAME(BlockType.OTHER, EndKind.NONE),
   117     FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
   119     H1(BlockType.BLOCK, EndKind.REQUIRED),
   120     H2(BlockType.BLOCK, EndKind.REQUIRED),
   121     H3(BlockType.BLOCK, EndKind.REQUIRED),
   122     H4(BlockType.BLOCK, EndKind.REQUIRED),
   123     H5(BlockType.BLOCK, EndKind.REQUIRED),
   124     H6(BlockType.BLOCK, EndKind.REQUIRED),
   126     HEAD(BlockType.OTHER, EndKind.REQUIRED),
   128     HR(BlockType.BLOCK, EndKind.NONE,
   129             attrs(AttrKind.OK, WIDTH)), // OK in 4.01; not allowed in 5
   131     HTML(BlockType.OTHER, EndKind.REQUIRED),
   133     I(BlockType.INLINE, EndKind.REQUIRED,
   134             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   136     IMG(BlockType.INLINE, EndKind.NONE,
   137             attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
   138             attrs(AttrKind.OBSOLETE, NAME),
   139             attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
   141     LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   142             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   143             attrs(AttrKind.OK, VALUE)),
   145     LINK(BlockType.OTHER, EndKind.NONE),
   147     MENU(BlockType.BLOCK, EndKind.REQUIRED) {
   148         @Override
   149         public boolean accepts(HtmlTag t) {
   150             return (t == LI);
   151         }
   152     },
   154     META(BlockType.OTHER, EndKind.NONE),
   156     NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
   158     NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
   160     OL(BlockType.BLOCK, EndKind.REQUIRED,
   161             EnumSet.of(Flag.EXPECT_CONTENT),
   162             attrs(AttrKind.OK, START, TYPE)) {
   163         @Override
   164         public boolean accepts(HtmlTag t) {
   165             return (t == LI);
   166         }
   167     },
   169     P(BlockType.BLOCK, EndKind.OPTIONAL,
   170             EnumSet.of(Flag.EXPECT_CONTENT),
   171             attrs(AttrKind.USE_CSS, ALIGN)),
   173     PRE(BlockType.BLOCK, EndKind.REQUIRED,
   174             EnumSet.of(Flag.EXPECT_CONTENT)) {
   175         @Override
   176         public boolean accepts(HtmlTag t) {
   177             switch (t) {
   178                 case IMG: case BIG: case SMALL: case SUB: case SUP:
   179                     return false;
   180                 default:
   181                     return (t.blockType == BlockType.INLINE);
   182             }
   183         }
   184     },
   186     SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
   188     SMALL(BlockType.INLINE, EndKind.REQUIRED,
   189             EnumSet.of(Flag.EXPECT_CONTENT)),
   191     SPAN(BlockType.INLINE, EndKind.REQUIRED,
   192             EnumSet.of(Flag.EXPECT_CONTENT)),
   194     STRONG(BlockType.INLINE, EndKind.REQUIRED,
   195             EnumSet.of(Flag.EXPECT_CONTENT)),
   197     SUB(BlockType.INLINE, EndKind.REQUIRED,
   198             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   200     SUP(BlockType.INLINE, EndKind.REQUIRED,
   201             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   203     TABLE(BlockType.BLOCK, EndKind.REQUIRED,
   204             EnumSet.of(Flag.EXPECT_CONTENT),
   205             attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
   206                 CELLPADDING, CELLSPACING, WIDTH), // width OK in 4.01; not allowed in 5
   207             attrs(AttrKind.USE_CSS, ALIGN, BGCOLOR)) {
   208         @Override
   209         public boolean accepts(HtmlTag t) {
   210             switch (t) {
   211                 case CAPTION:
   212                 case THEAD: case TBODY: case TFOOT:
   213                 case TR: // HTML 3.2
   214                     return true;
   215                 default:
   216                     return false;
   217             }
   218         }
   219     },
   221     TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   222             EnumSet.of(Flag.EXPECT_CONTENT),
   223             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   224         @Override
   225         public boolean accepts(HtmlTag t) {
   226             return (t == TR);
   227         }
   228     },
   230     TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   231             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   232             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   233                 ALIGN, CHAR, CHAROFF, VALIGN),
   234             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   236     TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   237             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   238         @Override
   239         public boolean accepts(HtmlTag t) {
   240             return (t == TR);
   241         }
   242     },
   244     TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   245             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   246             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   247                 ALIGN, CHAR, CHAROFF, VALIGN),
   248             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   250     THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   251             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   252         @Override
   253         public boolean accepts(HtmlTag t) {
   254             return (t == TR);
   255         }
   256     },
   258     TITLE(BlockType.OTHER, EndKind.REQUIRED),
   260     TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   261             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
   262             attrs(AttrKind.USE_CSS, BGCOLOR)) {
   263         @Override
   264         public boolean accepts(HtmlTag t) {
   265             return (t == TH) || (t == TD);
   266         }
   267     },
   269     TT(BlockType.INLINE, EndKind.REQUIRED,
   270             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   272     U(BlockType.INLINE, EndKind.REQUIRED,
   273             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   275     UL(BlockType.BLOCK, EndKind.REQUIRED,
   276             EnumSet.of(Flag.EXPECT_CONTENT),
   277             attrs(AttrKind.OK, COMPACT, TYPE)) { // OK in 4.01; not allowed in 5
   278         @Override
   279         public boolean accepts(HtmlTag t) {
   280             return (t == LI);
   281         }
   282     },
   284     VAR(BlockType.INLINE, EndKind.REQUIRED);
   286     /**
   287      * Enum representing the type of HTML element.
   288      */
   289     public static enum BlockType {
   290         BLOCK,
   291         INLINE,
   292         LIST_ITEM,
   293         TABLE_ITEM,
   294         OTHER;
   295     }
   297     /**
   298      * Enum representing HTML end tag requirement.
   299      */
   300     public static enum EndKind {
   301         NONE,
   302         OPTIONAL,
   303         REQUIRED;
   304     }
   306     public static enum Flag {
   307         ACCEPTS_BLOCK,
   308         ACCEPTS_INLINE,
   309         EXPECT_CONTENT,
   310         NO_NEST
   311     }
   313     public static enum Attr {
   314         ABBR,
   315         ALIGN,
   316         ALT,
   317         AXIS,
   318         BGCOLOR,
   319         BORDER,
   320         CELLSPACING,
   321         CELLPADDING,
   322         CHAR,
   323         CHAROFF,
   324         CLEAR,
   325         CLASS,
   326         COLOR,
   327         COLSPAN,
   328         COMPACT,
   329         FACE,
   330         FRAME,
   331         HEADERS,
   332         HEIGHT,
   333         HREF,
   334         HSPACE,
   335         ID,
   336         NAME,
   337         NOWRAP,
   338         REVERSED,
   339         ROWSPAN,
   340         RULES,
   341         SCOPE,
   342         SIZE,
   343         SPACE,
   344         SRC,
   345         START,
   346         STYLE,
   347         SUMMARY,
   348         TARGET,
   349         TYPE,
   350         VALIGN,
   351         VALUE,
   352         VSPACE,
   353         WIDTH;
   355         public String getText() {
   356             return StringUtils.toLowerCase(name());
   357         }
   359         static final Map<String,Attr> index = new HashMap<String,Attr>();
   360         static {
   361             for (Attr t: values()) {
   362                 index.put(t.getText(), t);
   363             }
   364         }
   365     }
   367     public static enum AttrKind {
   368         INVALID,
   369         OBSOLETE,
   370         USE_CSS,
   371         OK
   372     }
   374     // This class exists to avoid warnings from using parameterized vararg type
   375     // Map<Attr,AttrKind> in signature of HtmlTag constructor.
   376     private static class AttrMap extends EnumMap<Attr,AttrKind>  {
   377         private static final long serialVersionUID = 0;
   378         AttrMap() {
   379             super(Attr.class);
   380         }
   381     }
   384     public final BlockType blockType;
   385     public final EndKind endKind;
   386     public final Set<Flag> flags;
   387     private final Map<Attr,AttrKind> attrs;
   389     HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
   390         this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
   391     }
   393     HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
   394         this.blockType = blockType;
   395         this.endKind = endKind;
   396         this.flags = flags;
   397         this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
   398         for (Map<Attr,AttrKind> m: attrMaps)
   399             this.attrs.putAll(m);
   400         attrs.put(Attr.CLASS, AttrKind.OK);
   401         attrs.put(Attr.ID, AttrKind.OK);
   402         attrs.put(Attr.STYLE, AttrKind.OK);
   403     }
   405     public boolean accepts(HtmlTag t) {
   406         if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
   407             return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
   408         } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
   409             return (t.blockType == BlockType.BLOCK);
   410         } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
   411             return (t.blockType == BlockType.INLINE);
   412         } else
   413             switch (blockType) {
   414                 case BLOCK:
   415                 case INLINE:
   416                     return (t.blockType == BlockType.INLINE);
   417                 case OTHER:
   418                     // OTHER tags are invalid in doc comments, and will be
   419                     // reported separately, so silently accept/ignore any content
   420                     return true;
   421                 default:
   422                     // any combination which could otherwise arrive here
   423                     // ought to have been handled in an overriding method
   424                     throw new AssertionError(this + ":" + t);
   425             }
   426     }
   428     public boolean acceptsText() {
   429         // generally, anywhere we can put text we can also put inline tag
   430         // so check if a typical inline tag is allowed
   431         return accepts(B);
   432     }
   434     public String getText() {
   435         return StringUtils.toLowerCase(name());
   436     }
   438     public Attr getAttr(Name attrName) {
   439         return Attr.index.get(StringUtils.toLowerCase(attrName.toString()));
   440     }
   442     public AttrKind getAttrKind(Name attrName) {
   443         AttrKind k = attrs.get(getAttr(attrName)); // null-safe
   444         return (k == null) ? AttrKind.INVALID : k;
   445     }
   447     private static AttrMap attrs(AttrKind k, Attr... attrs) {
   448         AttrMap map = new AttrMap();
   449         for (Attr a: attrs) map.put(a, k);
   450         return map;
   451     }
   453     private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
   454     static {
   455         for (HtmlTag t: values()) {
   456             index.put(t.getText(), t);
   457         }
   458     }
   460     static HtmlTag get(Name tagName) {
   461         return index.get(StringUtils.toLowerCase(tagName.toString()));
   462     }
   464 }

mercurial