1 /*
   2  * Copyright (c) 1998, 2008, 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  */
  25 package javax.swing.text.html;
  26 
  27 import java.io.*;
  28 import java.util.Hashtable;
  29 import javax.swing.text.AttributeSet;
  30 import javax.swing.text.StyleConstants;
  31 import javax.swing.text.StyleContext;
  32 
  33 /**
  34  * Constants used in the <code>HTMLDocument</code>.  These
  35  * are basically tag and attribute definitions.
  36  *
  37  * @author  Timothy Prinzing
  38  * @author  Sunita Mani
  39  *
  40  */
  41 public class HTML {
  42 
  43     /**
  44      * Typesafe enumeration for an HTML tag.  Although the
  45      * set of HTML tags is a closed set, we have left the
  46      * set open so that people can add their own tag types
  47      * to their custom parser and still communicate to the
  48      * reader.
  49      */
  50     public static class Tag {
  51 
  52         /** @since 1.3 */
  53         public Tag() {}
  54 
  55         /**
  56          * Creates a new <code>Tag</code> with the specified <code>id</code>,
  57          * and with <code>causesBreak</code> and <code>isBlock</code>
  58          * set to <code>false</code>.
  59          *
  60          * @param id  the id of the new tag
  61          */
  62         protected Tag(String id) {
  63             this(id, false, false);
  64         }
  65 
  66         /**
  67          * Creates a new <code>Tag</code> with the specified <code>id</code>;
  68          * <code>causesBreak</code> and <code>isBlock</code> are defined
  69          * by the user.
  70          *
  71          * @param id the id of the new tag
  72          * @param causesBreak  <code>true</code> if this tag
  73          *    causes a break to the flow of data
  74          * @param isBlock <code>true</code> if the tag is used
  75          *    to add structure to a document
  76          */
  77         protected Tag(String id, boolean causesBreak, boolean isBlock) {
  78             name = id;
  79             this.breakTag = causesBreak;
  80             this.blockTag = isBlock;
  81         }
  82 
  83         /**
  84          * Returns <code>true</code> if this tag is a block
  85          * tag, which is a tag used to add structure to a
  86          * document.
  87          *
  88          * @return <code>true</code> if this tag is a block
  89          *   tag, otherwise returns <code>false</code>
  90          */
  91         public boolean isBlock() {
  92             return blockTag;
  93         }
  94 
  95         /**
  96          * Returns <code>true</code> if this tag causes a
  97          * line break to the flow of data, otherwise returns
  98          * <code>false</code>.
  99          *
 100          * @return <code>true</code> if this tag causes a
 101          *   line break to the flow of data, otherwise returns
 102          *   <code>false</code>
 103          */
 104         public boolean breaksFlow() {
 105             return breakTag;
 106         }
 107 
 108         /**
 109          * Returns <code>true</code> if this tag is pre-formatted,
 110          * which is true if the tag is either <code>PRE</code> or
 111          * <code>TEXTAREA</code>.
 112          *
 113          * @return <code>true</code> if this tag is pre-formatted,
 114          *   otherwise returns <code>false</code>
 115          */
 116         public boolean isPreformatted() {
 117             return (this == PRE || this == TEXTAREA);
 118         }
 119 
 120         /**
 121          * Returns the string representation of the
 122          * tag.
 123          *
 124          * @return the <code>String</code> representation of the tag
 125          */
 126         public String toString() {
 127             return name;
 128         }
 129 
 130         /**
 131          * Returns <code>true</code> if this tag is considered to be a paragraph
 132          * in the internal HTML model. <code>false</code> - otherwise.
 133          *
 134          * @return <code>true</code> if this tag is considered to be a paragraph
 135          *         in the internal HTML model. <code>false</code> - otherwise.
 136          * @see HTMLDocument.HTMLReader.ParagraphAction
 137          */
 138         boolean isParagraph() {
 139             return (
 140                 this == P
 141                    || this == IMPLIED
 142                    || this == DT
 143                    || this == H1
 144                    || this == H2
 145                    || this == H3
 146                    || this == H4
 147                    || this == H5
 148                    || this == H6
 149             );
 150         }
 151 
 152         boolean blockTag;
 153         boolean breakTag;
 154         String name;
 155         boolean unknown;
 156 
 157         // --- Tag Names -----------------------------------
 158 
 159         public static final Tag A = new Tag("a");
 160         public static final Tag ADDRESS = new Tag("address");
 161         public static final Tag APPLET = new Tag("applet");
 162         public static final Tag AREA = new Tag("area");
 163         public static final Tag B = new Tag("b");
 164         public static final Tag BASE = new Tag("base");
 165         public static final Tag BASEFONT = new Tag("basefont");
 166         public static final Tag BIG = new Tag("big");
 167         public static final Tag BLOCKQUOTE = new Tag("blockquote", true, true);
 168         public static final Tag BODY = new Tag("body", true, true);
 169         public static final Tag BR = new Tag("br", true, false);
 170         public static final Tag CAPTION = new Tag("caption");
 171         public static final Tag CENTER = new Tag("center", true, false);
 172         public static final Tag CITE = new Tag("cite");
 173         public static final Tag CODE = new Tag("code");
 174         public static final Tag DD = new Tag("dd", true, true);
 175         public static final Tag DFN = new Tag("dfn");
 176         public static final Tag DIR = new Tag("dir", true, true);
 177         public static final Tag DIV = new Tag("div", true, true);
 178         public static final Tag DL = new Tag("dl", true, true);
 179         public static final Tag DT = new Tag("dt", true, true);
 180         public static final Tag EM = new Tag("em");
 181         public static final Tag FONT = new Tag("font");
 182         public static final Tag FORM = new Tag("form", true, false);
 183         public static final Tag FRAME = new Tag("frame");
 184         public static final Tag FRAMESET = new Tag("frameset");
 185         public static final Tag H1 = new Tag("h1", true, true);
 186         public static final Tag H2 = new Tag("h2", true, true);
 187         public static final Tag H3 = new Tag("h3", true, true);
 188         public static final Tag H4 = new Tag("h4", true, true);
 189         public static final Tag H5 = new Tag("h5", true, true);
 190         public static final Tag H6 = new Tag("h6", true, true);
 191         public static final Tag HEAD = new Tag("head", true, true);
 192         public static final Tag HR = new Tag("hr", true, false);
 193         public static final Tag HTML = new Tag("html", true, false);
 194         public static final Tag I = new Tag("i");
 195         public static final Tag IMG = new Tag("img");
 196         public static final Tag INPUT = new Tag("input");
 197         public static final Tag ISINDEX = new Tag("isindex", true, false);
 198         public static final Tag KBD = new Tag("kbd");
 199         public static final Tag LI = new Tag("li", true, true);
 200         public static final Tag LINK = new Tag("link");
 201         public static final Tag MAP = new Tag("map");
 202         public static final Tag MENU = new Tag("menu", true, true);
 203         public static final Tag META = new Tag("meta");
 204         /*public*/ static final Tag NOBR = new Tag("nobr");
 205         public static final Tag NOFRAMES = new Tag("noframes", true, true);
 206         public static final Tag OBJECT = new Tag("object");
 207         public static final Tag OL = new Tag("ol", true, true);
 208         public static final Tag OPTION = new Tag("option");
 209         public static final Tag P = new Tag("p", true, true);
 210         public static final Tag PARAM = new Tag("param");
 211         public static final Tag PRE = new Tag("pre", true, true);
 212         public static final Tag SAMP = new Tag("samp");
 213         public static final Tag SCRIPT = new Tag("script");
 214         public static final Tag SELECT = new Tag("select");
 215         public static final Tag SMALL = new Tag("small");
 216         public static final Tag SPAN = new Tag("span");
 217         public static final Tag STRIKE = new Tag("strike");
 218         public static final Tag S = new Tag("s");
 219         public static final Tag STRONG = new Tag("strong");
 220         public static final Tag STYLE = new Tag("style");
 221         public static final Tag SUB = new Tag("sub");
 222         public static final Tag SUP = new Tag("sup");
 223         public static final Tag TABLE = new Tag("table", false, true);
 224         public static final Tag TD = new Tag("td", true, true);
 225         public static final Tag TEXTAREA = new Tag("textarea");
 226         public static final Tag TH = new Tag("th", true, true);
 227         public static final Tag TITLE = new Tag("title", true, true);
 228         public static final Tag TR = new Tag("tr", false, true);
 229         public static final Tag TT = new Tag("tt");
 230         public static final Tag U = new Tag("u");
 231         public static final Tag UL = new Tag("ul", true, true);
 232         public static final Tag VAR = new Tag("var");
 233 
 234         /**
 235          * All text content must be in a paragraph element.
 236          * If a paragraph didn't exist when content was
 237          * encountered, a paragraph is manufactured.
 238          * <p>
 239          * This is a tag synthesized by the HTML reader.
 240          * Since elements are identified by their tag type,
 241          * we create a some fake tag types to mark the elements
 242          * that were manufactured.
 243          */
 244         public static final Tag IMPLIED = new Tag("p-implied");
 245 
 246         /**
 247          * All text content is labeled with this tag.
 248          * <p>
 249          * This is a tag synthesized by the HTML reader.
 250          * Since elements are identified by their tag type,
 251          * we create a some fake tag types to mark the elements
 252          * that were manufactured.
 253          */
 254         public static final Tag CONTENT = new Tag("content");
 255 
 256         /**
 257          * All comments are labeled with this tag.
 258          * <p>
 259          * This is a tag synthesized by the HTML reader.
 260          * Since elements are identified by their tag type,
 261          * we create a some fake tag types to mark the elements
 262          * that were manufactured.
 263          */
 264         public static final Tag COMMENT = new Tag("comment");
 265 
 266         static final Tag allTags[]  = {
 267             A, ADDRESS, APPLET, AREA, B, BASE, BASEFONT, BIG,
 268             BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
 269             DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
 270             FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
 271             I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
 272             META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
 273             PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
 274             STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
 275             TH, TITLE, TR, TT, U, UL, VAR
 276         };
 277 
 278         static {
 279             // Force HTMLs static initialize to be loaded.
 280             getTag("html");
 281         }
 282     }
 283 
 284     // There is no unique instance of UnknownTag, so we allow it to be
 285     // Serializable.
 286     public static class UnknownTag extends Tag implements Serializable {
 287 
 288         /**
 289          * Creates a new <code>UnknownTag</code> with the specified
 290          * <code>id</code>.
 291          * @param id the id of the new tag
 292          */
 293         public UnknownTag(String id) {
 294             super(id);
 295         }
 296 
 297         /**
 298          * Returns the hash code which corresponds to the string
 299          * for this tag.
 300          */
 301         public int hashCode() {
 302             return toString().hashCode();
 303         }
 304 
 305         /**
 306          * Compares this object to the specified object.
 307          * The result is <code>true</code> if and only if the argument is not
 308          * <code>null</code> and is an <code>UnknownTag</code> object
 309          * with the same name.
 310          *
 311          * @param     obj   the object to compare this tag with
 312          * @return    <code>true</code> if the objects are equal;
 313          *            <code>false</code> otherwise
 314          */
 315         public boolean equals(Object obj) {
 316             if (obj instanceof UnknownTag) {
 317                 return toString().equals(obj.toString());
 318             }
 319             return false;
 320         }
 321 
 322         private void writeObject(java.io.ObjectOutputStream s)
 323                      throws IOException {
 324             s.defaultWriteObject();
 325             s.writeBoolean(blockTag);
 326             s.writeBoolean(breakTag);
 327             s.writeBoolean(unknown);
 328             s.writeObject(name);
 329         }
 330 
 331         private void readObject(ObjectInputStream s)
 332             throws ClassNotFoundException, IOException {
 333             s.defaultReadObject();
 334             blockTag = s.readBoolean();
 335             breakTag = s.readBoolean();
 336             unknown = s.readBoolean();
 337             name = (String)s.readObject();
 338         }
 339     }
 340 
 341     /**
 342      * Typesafe enumeration representing an HTML
 343      * attribute.
 344      */
 345     public static final class Attribute {
 346 
 347         /**
 348          * Creates a new <code>Attribute</code> with the specified
 349          * <code>id</code>.
 350          *
 351          * @param id the id of the new <code>Attribute</code>
 352          */
 353         Attribute(String id) {
 354             name = id;
 355         }
 356 
 357         /**
 358          * Returns the string representation of this attribute.
 359          * @return the string representation of this attribute
 360          */
 361         public String toString() {
 362             return name;
 363         }
 364 
 365         private String name;
 366 
 367         public static final Attribute SIZE = new Attribute("size");
 368         public static final Attribute COLOR = new Attribute("color");
 369         public static final Attribute CLEAR = new Attribute("clear");
 370         public static final Attribute BACKGROUND = new Attribute("background");
 371         public static final Attribute BGCOLOR = new Attribute("bgcolor");
 372         public static final Attribute TEXT = new Attribute("text");
 373         public static final Attribute LINK = new Attribute("link");
 374         public static final Attribute VLINK = new Attribute("vlink");
 375         public static final Attribute ALINK = new Attribute("alink");
 376         public static final Attribute WIDTH = new Attribute("width");
 377         public static final Attribute HEIGHT = new Attribute("height");
 378         public static final Attribute ALIGN = new Attribute("align");
 379         public static final Attribute NAME = new Attribute("name");
 380         public static final Attribute HREF = new Attribute("href");
 381         public static final Attribute REL = new Attribute("rel");
 382         public static final Attribute REV = new Attribute("rev");
 383         public static final Attribute TITLE = new Attribute("title");
 384         public static final Attribute TARGET = new Attribute("target");
 385         public static final Attribute SHAPE = new Attribute("shape");
 386         public static final Attribute COORDS = new Attribute("coords");
 387         public static final Attribute ISMAP = new Attribute("ismap");
 388         public static final Attribute NOHREF = new Attribute("nohref");
 389         public static final Attribute ALT = new Attribute("alt");
 390         public static final Attribute ID = new Attribute("id");
 391         public static final Attribute SRC = new Attribute("src");
 392         public static final Attribute HSPACE = new Attribute("hspace");
 393         public static final Attribute VSPACE = new Attribute("vspace");
 394         public static final Attribute USEMAP = new Attribute("usemap");
 395         public static final Attribute LOWSRC = new Attribute("lowsrc");
 396         public static final Attribute CODEBASE = new Attribute("codebase");
 397         public static final Attribute CODE = new Attribute("code");
 398         public static final Attribute ARCHIVE = new Attribute("archive");
 399         public static final Attribute VALUE = new Attribute("value");
 400         public static final Attribute VALUETYPE = new Attribute("valuetype");
 401         public static final Attribute TYPE = new Attribute("type");
 402         public static final Attribute CLASS = new Attribute("class");
 403         public static final Attribute STYLE = new Attribute("style");
 404         public static final Attribute LANG = new Attribute("lang");
 405         public static final Attribute FACE = new Attribute("face");
 406         public static final Attribute DIR = new Attribute("dir");
 407         public static final Attribute DECLARE = new Attribute("declare");
 408         public static final Attribute CLASSID = new Attribute("classid");
 409         public static final Attribute DATA = new Attribute("data");
 410         public static final Attribute CODETYPE = new Attribute("codetype");
 411         public static final Attribute STANDBY = new Attribute("standby");
 412         public static final Attribute BORDER = new Attribute("border");
 413         public static final Attribute SHAPES = new Attribute("shapes");
 414         public static final Attribute NOSHADE = new Attribute("noshade");
 415         public static final Attribute COMPACT = new Attribute("compact");
 416         public static final Attribute START = new Attribute("start");
 417         public static final Attribute ACTION = new Attribute("action");
 418         public static final Attribute METHOD = new Attribute("method");
 419         public static final Attribute ENCTYPE = new Attribute("enctype");
 420         public static final Attribute CHECKED = new Attribute("checked");
 421         public static final Attribute MAXLENGTH = new Attribute("maxlength");
 422         public static final Attribute MULTIPLE = new Attribute("multiple");
 423         public static final Attribute SELECTED = new Attribute("selected");
 424         public static final Attribute ROWS = new Attribute("rows");
 425         public static final Attribute COLS = new Attribute("cols");
 426         public static final Attribute DUMMY = new Attribute("dummy");
 427         public static final Attribute CELLSPACING = new Attribute("cellspacing");
 428         public static final Attribute CELLPADDING = new Attribute("cellpadding");
 429         public static final Attribute VALIGN = new Attribute("valign");
 430         public static final Attribute HALIGN = new Attribute("halign");
 431         public static final Attribute NOWRAP = new Attribute("nowrap");
 432         public static final Attribute ROWSPAN = new Attribute("rowspan");
 433         public static final Attribute COLSPAN = new Attribute("colspan");
 434         public static final Attribute PROMPT = new Attribute("prompt");
 435         public static final Attribute HTTPEQUIV = new Attribute("http-equiv");
 436         public static final Attribute CONTENT = new Attribute("content");
 437         public static final Attribute LANGUAGE = new Attribute("language");
 438         public static final Attribute VERSION = new Attribute("version");
 439         public static final Attribute N = new Attribute("n");
 440         public static final Attribute FRAMEBORDER = new Attribute("frameborder");
 441         public static final Attribute MARGINWIDTH = new Attribute("marginwidth");
 442         public static final Attribute MARGINHEIGHT = new Attribute("marginheight");
 443         public static final Attribute SCROLLING = new Attribute("scrolling");
 444         public static final Attribute NORESIZE = new Attribute("noresize");
 445         public static final Attribute ENDTAG = new Attribute("endtag");
 446         public static final Attribute COMMENT = new Attribute("comment");
 447         static final Attribute MEDIA = new Attribute("media");
 448 
 449         static final Attribute allAttributes[] = {
 450             FACE,
 451             COMMENT,
 452             SIZE,
 453             COLOR,
 454             CLEAR,
 455             BACKGROUND,
 456             BGCOLOR,
 457             TEXT,
 458             LINK,
 459             VLINK,
 460             ALINK,
 461             WIDTH,
 462             HEIGHT,
 463             ALIGN,
 464             NAME,
 465             HREF,
 466             REL,
 467             REV,
 468             TITLE,
 469             TARGET,
 470             SHAPE,
 471             COORDS,
 472             ISMAP,
 473             NOHREF,
 474             ALT,
 475             ID,
 476             SRC,
 477             HSPACE,
 478             VSPACE,
 479             USEMAP,
 480             LOWSRC,
 481             CODEBASE,
 482             CODE,
 483             ARCHIVE,
 484             VALUE,
 485             VALUETYPE,
 486             TYPE,
 487             CLASS,
 488             STYLE,
 489             LANG,
 490             DIR,
 491             DECLARE,
 492             CLASSID,
 493             DATA,
 494             CODETYPE,
 495             STANDBY,
 496             BORDER,
 497             SHAPES,
 498             NOSHADE,
 499             COMPACT,
 500             START,
 501             ACTION,
 502             METHOD,
 503             ENCTYPE,
 504             CHECKED,
 505             MAXLENGTH,
 506             MULTIPLE,
 507             SELECTED,
 508             ROWS,
 509             COLS,
 510             DUMMY,
 511             CELLSPACING,
 512             CELLPADDING,
 513             VALIGN,
 514             HALIGN,
 515             NOWRAP,
 516             ROWSPAN,
 517             COLSPAN,
 518             PROMPT,
 519             HTTPEQUIV,
 520             CONTENT,
 521             LANGUAGE,
 522             VERSION,
 523             N,
 524             FRAMEBORDER,
 525             MARGINWIDTH,
 526             MARGINHEIGHT,
 527             SCROLLING,
 528             NORESIZE,
 529             MEDIA,
 530             ENDTAG
 531         };
 532     }
 533 
 534     // The secret to 73, is that, given that the Hashtable contents
 535     // never change once the static initialization happens, the initial size
 536     // that the hashtable grew to was determined, and then that very size
 537     // is used.
 538     //
 539     private static final Hashtable<String, Tag> tagHashtable = new Hashtable<String, Tag>(73);
 540 
 541     /** Maps from StyleConstant key to HTML.Tag. */
 542     private static final Hashtable<Object, Tag> scMapping = new Hashtable<Object, Tag>(8);
 543 
 544     static {
 545 
 546         for (int i = 0; i < Tag.allTags.length; i++ ) {
 547             tagHashtable.put(Tag.allTags[i].toString(), Tag.allTags[i]);
 548             StyleContext.registerStaticAttributeKey(Tag.allTags[i]);
 549         }
 550         StyleContext.registerStaticAttributeKey(Tag.IMPLIED);
 551         StyleContext.registerStaticAttributeKey(Tag.CONTENT);
 552         StyleContext.registerStaticAttributeKey(Tag.COMMENT);
 553         for (int i = 0; i < Attribute.allAttributes.length; i++) {
 554             StyleContext.registerStaticAttributeKey(Attribute.
 555                                                     allAttributes[i]);
 556         }
 557         StyleContext.registerStaticAttributeKey(HTML.NULL_ATTRIBUTE_VALUE);
 558         scMapping.put(StyleConstants.Bold, Tag.B);
 559         scMapping.put(StyleConstants.Italic, Tag.I);
 560         scMapping.put(StyleConstants.Underline, Tag.U);
 561         scMapping.put(StyleConstants.StrikeThrough, Tag.STRIKE);
 562         scMapping.put(StyleConstants.Superscript, Tag.SUP);
 563         scMapping.put(StyleConstants.Subscript, Tag.SUB);
 564         scMapping.put(StyleConstants.FontFamily, Tag.FONT);
 565         scMapping.put(StyleConstants.FontSize, Tag.FONT);
 566     }
 567 
 568     /**
 569      * Returns the set of actual HTML tags that
 570      * are recognized by the default HTML reader.
 571      * This set does not include tags that are
 572      * manufactured by the reader.
 573      */
 574     public static Tag[] getAllTags() {
 575         Tag[] tags = new Tag[Tag.allTags.length];
 576         System.arraycopy(Tag.allTags, 0, tags, 0, Tag.allTags.length);
 577         return tags;
 578     }
 579 
 580     /**
 581      * Fetches a tag constant for a well-known tag name (i.e. one of
 582      * the tags in the set {A, ADDRESS, APPLET, AREA, B,
 583      * BASE, BASEFONT, BIG,
 584      * BLOCKQUOTE, BODY, BR, CAPTION, CENTER, CITE, CODE,
 585      * DD, DFN, DIR, DIV, DL, DT, EM, FONT, FORM, FRAME,
 586      * FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, HTML,
 587      * I, IMG, INPUT, ISINDEX, KBD, LI, LINK, MAP, MENU,
 588      * META, NOBR, NOFRAMES, OBJECT, OL, OPTION, P, PARAM,
 589      * PRE, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, S,
 590      * STRONG, STYLE, SUB, SUP, TABLE, TD, TEXTAREA,
 591      * TH, TITLE, TR, TT, U, UL, VAR}.  If the given
 592      * name does not represent one of the well-known tags, then
 593      * <code>null</code> will be returned.
 594      *
 595      * @param tagName the <code>String</code> name requested
 596      * @return a tag constant corresponding to the <code>tagName</code>,
 597      *    or <code>null</code> if not found
 598      */
 599     public static Tag getTag(String tagName) {
 600 
 601         Tag t =  tagHashtable.get(tagName);
 602         return (t == null ? null : t);
 603     }
 604 
 605     /**
 606      * Returns the HTML <code>Tag</code> associated with the
 607      * <code>StyleConstants</code> key <code>sc</code>.
 608      * If no matching <code>Tag</code> is found, returns
 609      * <code>null</code>.
 610      *
 611      * @param sc the <code>StyleConstants</code> key
 612      * @return tag which corresponds to <code>sc</code>, or
 613      *   <code>null</code> if not found
 614      */
 615     static Tag getTagForStyleConstantsKey(StyleConstants sc) {
 616         return scMapping.get(sc);
 617     }
 618 
 619     /**
 620      * Fetches an integer attribute value.  Attribute values
 621      * are stored as a string, and this is a convenience method
 622      * to convert to an actual integer.
 623      *
 624      * @param attr the set of attributes to use to try to fetch a value
 625      * @param key the key to use to fetch the value
 626      * @param def the default value to use if the attribute isn't
 627      *  defined or there is an error converting to an integer
 628      */
 629     public static int getIntegerAttributeValue(AttributeSet attr,
 630                                                Attribute key, int def) {
 631         int value = def;
 632         String istr = (String) attr.getAttribute(key);
 633         if (istr != null) {
 634             try {
 635                 value = Integer.valueOf(istr).intValue();
 636             } catch (NumberFormatException e) {
 637                 value = def;
 638             }
 639         }
 640         return value;
 641     }
 642 
 643     //  This is used in cases where the value for the attribute has not
 644     //  been specified.
 645     //
 646     public static final String NULL_ATTRIBUTE_VALUE = "#DEFAULT";
 647 
 648     // size determined similar to size of tagHashtable
 649     private static final Hashtable<String, Attribute> attHashtable = new Hashtable<String, Attribute>(77);
 650 
 651     static {
 652 
 653         for (int i = 0; i < Attribute.allAttributes.length; i++ ) {
 654             attHashtable.put(Attribute.allAttributes[i].toString(), Attribute.allAttributes[i]);
 655         }
 656     }
 657 
 658     /**
 659      * Returns the set of HTML attributes recognized.
 660      * @return the set of HTML attributes recognized
 661      */
 662     public static Attribute[] getAllAttributeKeys() {
 663         Attribute[] attributes = new Attribute[Attribute.allAttributes.length];
 664         System.arraycopy(Attribute.allAttributes, 0,
 665                          attributes, 0, Attribute.allAttributes.length);
 666         return attributes;
 667     }
 668 
 669     /**
 670      * Fetches an attribute constant for a well-known attribute name
 671      * (i.e. one of the attributes in the set {FACE, COMMENT, SIZE,
 672      * COLOR, CLEAR, BACKGROUND, BGCOLOR, TEXT, LINK, VLINK, ALINK,
 673      * WIDTH, HEIGHT, ALIGN, NAME, HREF, REL, REV, TITLE, TARGET,
 674      * SHAPE, COORDS, ISMAP, NOHREF, ALT, ID, SRC, HSPACE, VSPACE,
 675      * USEMAP, LOWSRC, CODEBASE, CODE, ARCHIVE, VALUE, VALUETYPE,
 676      * TYPE, CLASS, STYLE, LANG, DIR, DECLARE, CLASSID, DATA, CODETYPE,
 677      * STANDBY, BORDER, SHAPES, NOSHADE, COMPACT, START, ACTION, METHOD,
 678      * ENCTYPE, CHECKED, MAXLENGTH, MULTIPLE, SELECTED, ROWS, COLS,
 679      * DUMMY, CELLSPACING, CELLPADDING, VALIGN, HALIGN, NOWRAP, ROWSPAN,
 680      * COLSPAN, PROMPT, HTTPEQUIV, CONTENT, LANGUAGE, VERSION, N,
 681      * FRAMEBORDER, MARGINWIDTH, MARGINHEIGHT, SCROLLING, NORESIZE,
 682      * MEDIA, ENDTAG}).
 683      * If the given name does not represent one of the well-known attributes,
 684      * then <code>null</code> will be returned.
 685      *
 686      * @param attName the <code>String</code> requested
 687      * @return the <code>Attribute</code> corresponding to <code>attName</code>
 688      */
 689     public static Attribute getAttributeKey(String attName) {
 690         Attribute a = attHashtable.get(attName);
 691         if (a == null) {
 692           return null;
 693         }
 694         return a;
 695     }
 696 
 697 }