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

Wed, 23 Jan 2013 13:27:24 -0800

author
jjg
date
Wed, 23 Jan 2013 13:27:24 -0800
changeset 1521
71f35e4b93a5
parent 1507
967052c425a1
child 1793
391f97e270c2
permissions
-rw-r--r--

8006775: JSR 308: Compiler changes in JDK8
Reviewed-by: jjg
Contributed-by: mernst@cs.washington.edu, wmdietl@cs.washington.edu, mpapi@csail.mit.edu, mahmood@notnoop.com

jjg@1455 1 /*
jjg@1506 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jjg@1455 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@1455 4 *
jjg@1455 5 * This code is free software; you can redistribute it and/or modify it
jjg@1455 6 * under the terms of the GNU General Public License version 2 only, as
jjg@1455 7 * published by the Free Software Foundation. Oracle designates this
jjg@1455 8 * particular file as subject to the "Classpath" exception as provided
jjg@1455 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@1455 10 *
jjg@1455 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@1455 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@1455 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@1455 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@1455 15 * accompanied this code).
jjg@1455 16 *
jjg@1455 17 * You should have received a copy of the GNU General Public License version
jjg@1455 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@1455 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@1455 20 *
jjg@1455 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@1455 22 * or visit www.oracle.com if you need additional information or have any
jjg@1455 23 * questions.
jjg@1455 24 */
jjg@1455 25
jjg@1455 26 package com.sun.tools.doclint;
jjg@1455 27
jjg@1455 28 import java.util.Set;
jjg@1455 29 import java.util.Collections;
jjg@1455 30 import java.util.EnumMap;
jjg@1455 31 import java.util.EnumSet;
jjg@1455 32 import java.util.HashMap;
jjg@1455 33 import java.util.Map;
jjg@1455 34
jjg@1455 35 import javax.lang.model.element.Name;
jjg@1455 36
jjg@1455 37 import static com.sun.tools.doclint.HtmlTag.Attr.*;
jjg@1455 38
jjg@1455 39 /**
jjg@1455 40 * Enum representing HTML tags.
jjg@1455 41 *
jjg@1455 42 * The intent of this class is to embody the semantics of W3C HTML 4.01
jjg@1455 43 * to the extent supported/used by javadoc.
jjg@1455 44 *
jjg@1455 45 * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
jjg@1455 46 * Eventually, these two should be merged back together, and possibly made
jjg@1455 47 * public.
jjg@1455 48 *
jjg@1455 49 * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
jjg@1455 50 * @author Bhavesh Patel
jjg@1455 51 * @author Jonathan Gibbons (revised)
jjg@1455 52 */
jjg@1455 53 public enum HtmlTag {
jjg@1455 54 A(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 55 attrs(AttrKind.OK, HREF, TARGET, NAME)),
jjg@1455 56
jjg@1455 57 B(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 58 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 59
jjg@1507 60 BIG(BlockType.INLINE, EndKind.REQUIRED,
jjg@1507 61 EnumSet.of(Flag.EXPECT_CONTENT)),
jjg@1507 62
jjg@1507 63 BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 64 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
jjg@1455 65
jjg@1455 66 BODY(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 67
jjg@1455 68 BR(BlockType.INLINE, EndKind.NONE,
jjg@1455 69 attrs(AttrKind.USE_CSS, CLEAR)),
jjg@1455 70
jjg@1507 71 CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
jjg@1507 72 EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
jjg@1455 73
jjg@1507 74 CENTER(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 75 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
jjg@1455 76
jjg@1455 77 CITE(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 78 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 79
jjg@1455 80 CODE(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 81 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 82
jjg@1507 83 DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
jjg@1507 84 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
jjg@1455 85
jjg@1507 86 DIV(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 87 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
jjg@1455 88
jjg@1455 89 DL(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 90 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1507 91 attrs(AttrKind.USE_CSS, COMPACT)) {
jjg@1507 92 @Override
jjg@1507 93 public boolean accepts(HtmlTag t) {
jjg@1507 94 return (t == DT) || (t == DD);
jjg@1507 95 }
jjg@1507 96 },
jjg@1455 97
jjg@1507 98 DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
jjg@1507 99 EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
jjg@1455 100
jjg@1455 101 EM(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 102 EnumSet.of(Flag.NO_NEST)),
jjg@1455 103
jjg@1455 104 FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
jjg@1455 105 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1455 106 attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
jjg@1455 107
jjg@1455 108 FRAME(BlockType.OTHER, EndKind.NONE),
jjg@1455 109
jjg@1455 110 FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 111
jjg@1507 112 H1(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1507 113 H2(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1507 114 H3(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1507 115 H4(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1507 116 H5(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1507 117 H6(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1455 118
jjg@1455 119 HEAD(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 120
jjg@1455 121 HR(BlockType.BLOCK, EndKind.NONE),
jjg@1455 122
jjg@1455 123 HTML(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 124
jjg@1455 125 I(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 126 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 127
jjg@1455 128 IMG(BlockType.INLINE, EndKind.NONE,
jjg@1455 129 attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
jjg@1455 130 attrs(AttrKind.OBSOLETE, NAME),
jjg@1455 131 attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
jjg@1455 132
jjg@1507 133 LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
jjg@1507 134 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
jjg@1455 135
jjg@1455 136 LINK(BlockType.OTHER, EndKind.NONE),
jjg@1455 137
jjg@1507 138 MENU(BlockType.BLOCK, EndKind.REQUIRED) {
jjg@1507 139 @Override
jjg@1507 140 public boolean accepts(HtmlTag t) {
jjg@1507 141 return (t == LI);
jjg@1507 142 }
jjg@1507 143 },
jjg@1455 144
jjg@1455 145 META(BlockType.OTHER, EndKind.NONE),
jjg@1455 146
jjg@1455 147 NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 148
jjg@1507 149 NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
jjg@1455 150
jjg@1455 151 OL(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 152 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1507 153 attrs(AttrKind.USE_CSS, START, TYPE)){
jjg@1507 154 @Override
jjg@1507 155 public boolean accepts(HtmlTag t) {
jjg@1507 156 return (t == LI);
jjg@1507 157 }
jjg@1507 158 },
jjg@1455 159
jjg@1455 160 P(BlockType.BLOCK, EndKind.OPTIONAL,
jjg@1455 161 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1455 162 attrs(AttrKind.USE_CSS, ALIGN)),
jjg@1455 163
jjg@1507 164 PRE(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 165 EnumSet.of(Flag.EXPECT_CONTENT)) {
jjg@1507 166 @Override
jjg@1507 167 public boolean accepts(HtmlTag t) {
jjg@1507 168 switch (t) {
jjg@1507 169 case IMG: case BIG: case SMALL: case SUB: case SUP:
jjg@1507 170 return false;
jjg@1507 171 default:
jjg@1507 172 return (t.blockType == BlockType.INLINE);
jjg@1507 173 }
jjg@1507 174 }
jjg@1507 175 },
jjg@1455 176
jjg@1455 177 SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 178
jjg@1507 179 SMALL(BlockType.INLINE, EndKind.REQUIRED,
jjg@1507 180 EnumSet.of(Flag.EXPECT_CONTENT)),
jjg@1455 181
jjg@1455 182 SPAN(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 183 EnumSet.of(Flag.EXPECT_CONTENT)),
jjg@1455 184
jjg@1455 185 STRONG(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 186 EnumSet.of(Flag.EXPECT_CONTENT)),
jjg@1455 187
jjg@1455 188 SUB(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 189 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 190
jjg@1455 191 SUP(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 192 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 193
jjg@1455 194 TABLE(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 195 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1455 196 attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
jjg@1455 197 CELLPADDING, CELLSPACING),
jjg@1507 198 attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)) {
jjg@1507 199 @Override
jjg@1507 200 public boolean accepts(HtmlTag t) {
jjg@1507 201 switch (t) {
jjg@1507 202 case CAPTION:
jjg@1507 203 case THEAD: case TBODY: case TFOOT:
jjg@1507 204 case TR: // HTML 3.2
jjg@1507 205 return true;
jjg@1507 206 default:
jjg@1507 207 return false;
jjg@1507 208 }
jjg@1507 209 }
jjg@1507 210 },
jjg@1455 211
jjg@1507 212 TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
jjg@1507 213 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1507 214 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
jjg@1507 215 @Override
jjg@1507 216 public boolean accepts(HtmlTag t) {
jjg@1507 217 return (t == TR);
jjg@1507 218 }
jjg@1507 219 },
jjg@1455 220
jjg@1507 221 TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
jjg@1507 222 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
jjg@1455 223 attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
jjg@1455 224 ALIGN, CHAR, CHAROFF, VALIGN),
jjg@1455 225 attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
jjg@1455 226
jjg@1507 227 TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
jjg@1507 228 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
jjg@1507 229 @Override
jjg@1507 230 public boolean accepts(HtmlTag t) {
jjg@1507 231 return (t == TR);
jjg@1507 232 }
jjg@1507 233 },
jjg@1455 234
jjg@1507 235 TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
jjg@1507 236 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
jjg@1455 237 attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
jjg@1455 238 ALIGN, CHAR, CHAROFF, VALIGN),
jjg@1455 239 attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
jjg@1455 240
jjg@1507 241 THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
jjg@1507 242 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
jjg@1507 243 @Override
jjg@1507 244 public boolean accepts(HtmlTag t) {
jjg@1507 245 return (t == TR);
jjg@1507 246 }
jjg@1507 247 },
jjg@1455 248
jjg@1455 249 TITLE(BlockType.OTHER, EndKind.REQUIRED),
jjg@1455 250
jjg@1507 251 TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
jjg@1455 252 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
jjg@1507 253 attrs(AttrKind.USE_CSS, BGCOLOR)) {
jjg@1507 254 @Override
jjg@1507 255 public boolean accepts(HtmlTag t) {
jjg@1507 256 return (t == TH) || (t == TD);
jjg@1507 257 }
jjg@1507 258 },
jjg@1455 259
jjg@1455 260 TT(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 261 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 262
jjg@1455 263 U(BlockType.INLINE, EndKind.REQUIRED,
jjg@1455 264 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
jjg@1455 265
jjg@1455 266 UL(BlockType.BLOCK, EndKind.REQUIRED,
jjg@1507 267 EnumSet.of(Flag.EXPECT_CONTENT),
jjg@1507 268 attrs(AttrKind.USE_CSS, COMPACT, TYPE)){
jjg@1507 269 @Override
jjg@1507 270 public boolean accepts(HtmlTag t) {
jjg@1507 271 return (t == LI);
jjg@1507 272 }
jjg@1507 273 },
jjg@1455 274
jjg@1455 275 VAR(BlockType.INLINE, EndKind.REQUIRED);
jjg@1455 276
jjg@1455 277 /**
jjg@1455 278 * Enum representing the type of HTML element.
jjg@1455 279 */
jjg@1455 280 public static enum BlockType {
jjg@1455 281 BLOCK,
jjg@1455 282 INLINE,
jjg@1507 283 LIST_ITEM,
jjg@1507 284 TABLE_ITEM,
jjg@1455 285 OTHER;
jjg@1455 286 }
jjg@1455 287
jjg@1455 288 /**
jjg@1455 289 * Enum representing HTML end tag requirement.
jjg@1455 290 */
jjg@1455 291 public static enum EndKind {
jjg@1455 292 NONE,
jjg@1455 293 OPTIONAL,
jjg@1455 294 REQUIRED;
jjg@1455 295 }
jjg@1455 296
jjg@1455 297 public static enum Flag {
jjg@1507 298 ACCEPTS_BLOCK,
jjg@1507 299 ACCEPTS_INLINE,
jjg@1455 300 EXPECT_CONTENT,
jjg@1507 301 NO_NEST
jjg@1455 302 }
jjg@1455 303
jjg@1455 304 public static enum Attr {
jjg@1455 305 ABBR,
jjg@1455 306 ALIGN,
jjg@1455 307 ALT,
jjg@1455 308 AXIS,
jjg@1455 309 BGCOLOR,
jjg@1455 310 BORDER,
jjg@1455 311 CELLSPACING,
jjg@1455 312 CELLPADDING,
jjg@1455 313 CHAR,
jjg@1455 314 CHAROFF,
jjg@1455 315 CLEAR,
jjg@1455 316 CLASS,
jjg@1455 317 COLOR,
jjg@1455 318 COLSPAN,
jjg@1455 319 COMPACT,
jjg@1455 320 FACE,
jjg@1455 321 FRAME,
jjg@1455 322 HEADERS,
jjg@1455 323 HEIGHT,
jjg@1455 324 HREF,
jjg@1455 325 HSPACE,
jjg@1455 326 ID,
jjg@1455 327 NAME,
jjg@1455 328 NOWRAP,
jjg@1455 329 REVERSED,
jjg@1455 330 ROWSPAN,
jjg@1455 331 RULES,
jjg@1455 332 SCOPE,
jjg@1455 333 SIZE,
jjg@1455 334 SPACE,
jjg@1455 335 SRC,
jjg@1455 336 START,
jjg@1455 337 STYLE,
jjg@1455 338 SUMMARY,
jjg@1455 339 TARGET,
jjg@1455 340 TYPE,
jjg@1455 341 VALIGN,
jjg@1455 342 VSPACE,
jjg@1455 343 WIDTH;
jjg@1455 344
jjg@1455 345 public String getText() {
jjg@1455 346 return name().toLowerCase();
jjg@1455 347 }
jjg@1455 348
jjg@1455 349 static final Map<String,Attr> index = new HashMap<String,Attr>();
jjg@1455 350 static {
jjg@1455 351 for (Attr t: values()) {
jjg@1506 352 index.put(t.getText(), t);
jjg@1455 353 }
jjg@1455 354 }
jjg@1455 355 }
jjg@1455 356
jjg@1455 357 public static enum AttrKind {
jjg@1455 358 INVALID,
jjg@1455 359 OBSOLETE,
jjg@1455 360 USE_CSS,
jjg@1455 361 OK
jjg@1455 362 }
jjg@1455 363
jjg@1455 364 // This class exists to avoid warnings from using parameterized vararg type
jjg@1455 365 // Map<Attr,AttrKind> in signature of HtmlTag constructor.
jjg@1455 366 private static class AttrMap extends EnumMap<Attr,AttrKind> {
jjg@1455 367 private static final long serialVersionUID = 0;
jjg@1455 368 AttrMap() {
jjg@1455 369 super(Attr.class);
jjg@1455 370 }
jjg@1455 371 }
jjg@1455 372
jjg@1455 373
jjg@1455 374 public final BlockType blockType;
jjg@1455 375 public final EndKind endKind;
jjg@1455 376 public final Set<Flag> flags;
jjg@1455 377 private final Map<Attr,AttrKind> attrs;
jjg@1455 378
jjg@1455 379 HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
jjg@1455 380 this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
jjg@1455 381 }
jjg@1455 382
jjg@1455 383 HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
jjg@1455 384 this.blockType = blockType;
jjg@1507 385 this.endKind = endKind;
jjg@1507 386 this.flags = flags;
jjg@1455 387 this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
jjg@1455 388 for (Map<Attr,AttrKind> m: attrMaps)
jjg@1455 389 this.attrs.putAll(m);
jjg@1455 390 attrs.put(Attr.CLASS, AttrKind.OK);
jjg@1455 391 attrs.put(Attr.ID, AttrKind.OK);
jjg@1455 392 attrs.put(Attr.STYLE, AttrKind.OK);
jjg@1455 393 }
jjg@1455 394
jjg@1507 395 public boolean accepts(HtmlTag t) {
jjg@1507 396 if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
jjg@1507 397 return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
jjg@1507 398 } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
jjg@1507 399 return (t.blockType == BlockType.BLOCK);
jjg@1507 400 } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
jjg@1507 401 return (t.blockType == BlockType.INLINE);
jjg@1507 402 } else
jjg@1507 403 switch (blockType) {
jjg@1507 404 case BLOCK:
jjg@1507 405 case INLINE:
jjg@1507 406 return (t.blockType == BlockType.INLINE);
jjg@1507 407 case OTHER:
jjg@1507 408 // OTHER tags are invalid in doc comments, and will be
jjg@1507 409 // reported separately, so silently accept/ignore any content
jjg@1507 410 return true;
jjg@1507 411 default:
jjg@1507 412 // any combination which could otherwise arrive here
jjg@1507 413 // ought to have been handled in an overriding method
jjg@1507 414 throw new AssertionError(this + ":" + t);
jjg@1507 415 }
jjg@1507 416 }
jjg@1507 417
jjg@1507 418 public boolean acceptsText() {
jjg@1507 419 // generally, anywhere we can put text we can also put inline tag
jjg@1507 420 // so check if a typical inline tag is allowed
jjg@1507 421 return accepts(B);
jjg@1507 422 }
jjg@1507 423
jjg@1455 424 public String getText() {
jjg@1455 425 return name().toLowerCase();
jjg@1455 426 }
jjg@1455 427
jjg@1455 428 public Attr getAttr(Name attrName) {
jjg@1455 429 return Attr.index.get(attrName.toString().toLowerCase());
jjg@1455 430 }
jjg@1455 431
jjg@1455 432 public AttrKind getAttrKind(Name attrName) {
jjg@1455 433 AttrKind k = attrs.get(getAttr(attrName)); // null-safe
jjg@1455 434 return (k == null) ? AttrKind.INVALID : k;
jjg@1455 435 }
jjg@1455 436
jjg@1455 437 private static AttrMap attrs(AttrKind k, Attr... attrs) {
jjg@1455 438 AttrMap map = new AttrMap();
jjg@1455 439 for (Attr a: attrs) map.put(a, k);
jjg@1455 440 return map;
jjg@1455 441 }
jjg@1455 442
jjg@1455 443 private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
jjg@1455 444 static {
jjg@1455 445 for (HtmlTag t: values()) {
jjg@1506 446 index.put(t.getText(), t);
jjg@1455 447 }
jjg@1455 448 }
jjg@1455 449
jjg@1455 450 static HtmlTag get(Name tagName) {
jjg@1455 451 return index.get(tagName.toString().toLowerCase());
jjg@1455 452 }
jjg@1455 453 }

mercurial