/*
 * $Id: XhtmlDomElement.java,v 1.1.1.1 2002/09/30 15:08:51 smartine Exp $
 * Copyright (C) 1999-2000 David Brownell
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package xml.dom.xhtml;

import java.util.Hashtable;

import org.w3c.dom.*;
import org.w3c.dom.html.HTMLElement;
import xml.dom.*;


// $Id: XhtmlDomElement.java,v 1.1.1.1 2002/09/30 15:08:51 smartine Exp $

/**
 * <p> XHTML subclass of "DomElement", implementing HTMLElement and knowing
 * about its namespace and the legal element names in that namespace.
 *
 * <p>In the HTML DOM, the following HTML elements offer no further
 * functionality than is offered by this class (although they have non-XHTML
 * rules affecting case normalization in names):  HEAD, SUB, SUP, SPAN, BDO,
 * TT, I, EM, B, U, S, STRIKE, BIG, SMALL, EM, STRONG, CODE, DFN, SAMP, KBD,
 * VAR, CITE, ACRONYM, ABBR, DD, DT, NOFRAMES, NOSCRIPT, ADDRESS, CENTER.
 * Ninety or so other elements exist, and are defined to use subtypes of
 * the HTMLElement interface.  </p>
 *
 * <p> DOM Level 2 defines an HTMLElementCSS interface to support access
 * to the CSS style information for an element; this is not supported by
 * this implementation, since that is part of the "CSS" stylesheet feature.</p>
 *
 * <p> <em>NOTE: At this writing, constraints on legal XHTML attribute names
 * are not enforced. </em>
 *
 * @author David Brownell 
 * @version $Date: 2002/09/30 15:08:51 $
 */
public class XhtmlDomElement extends DomElement implements HTMLElement
{
    // all names in the XHTML element vocabulary
    private static final String	xhtmlElementNames [] = {
	"html", "head", "title", "base", "meta", "link", "style",
	"script", "noscript", "iframe", "noframes", "body", "div",
	"p", "h1", "h2", "h2", "h3", "h4", "h5", "h6", "ul", "ol",
	"menu", "dir", "li", "dl", "dt", "dd", "address", "hr", "pre",
	"blockquote", "center", "ins", "del", "a", "span", "bdo", "br",
	"em", "strong", "dfn", "code", "samp", "kbd", "var", "cite",
	"abbr", "acronym", "q", "sub", "sup", "tt", "i", "b", "big",
	"small", "u", "s", "strike", "basefont", "font", "object",
	"param", "applet", "img", "map", "area", "form", "label",
	"input", "select", "optgroup", "option", "textarea", "fieldset",
	"legend", "button", "isindex", "table", "caption", "thead",
	"tfoot", "tbody", "colgroup", "col", "tr", "th", "td",
	"frameset", "frame",
    };

    private static final Hashtable xhtmlElements;

    static {
	Hashtable ht = new Hashtable ((int)(xhtmlElementNames.length * 1.5));
	for (int i = 0; i < xhtmlElementNames.length; i++)
	    ht.put (xhtmlElementNames [i], xhtmlElementNames [i]);
	xhtmlElements = ht;
    }


    /**
     * Constructs an XHTML Element node associated with the specified document.
     *
     * <p>This constructor should only be invoked by a Document as part
     * of its createElement functionality, or through a subclass which is
     * similarly used by the Document class in a "Sub-DOM" style layer.
     *
     * @param owner The document with which this element is associated
     * @param name Name of this element, which may include a prefix
     * @exception DOMException NOT_SUPPORTED_ERR if the local part of
     *	the name is not in the XHTML 1.0 element vocabulary
     */
    protected XhtmlDomElement (Document owner, String name)
    {
	super (owner, XhtmlDomImpl.xhtmlNamespace, name);

	if (xhtmlElements.get (getLocalName ()) == null)
	    throw new DomEx (DomEx.NOT_SUPPORTED_ERR, name, null, 0);
    }

	// XXX should probably use namespace URIs for all attributes

    /** Returns the "id" attribute of this element, or null. */
    final public String getId ()
	{ return getAttribute ("id"); }

    /**
     * Assigns the "id" attribute of this element.
     * If the string is not an XML name, a DOM exception is reported.
     * If the element is an "a" element, or another of the HTML elements
     * for which a "name" attribute is defined, its "name" is also set to
     * ensure that these deprecated attributes remain consistent.
     */
    final public void setId (String id)
    {
	String	local = getLocalName ();

	DomDocument.verifyXmlName (id);

	setAttribute ("id", id);
	if ("a".equals (local) || "applet".equals (local)
		|| "frame".equals (local) || "iframe".equals (local)
		|| "img".equals (local) || "map".equals (local))
	    setAttribute ("name", id);
    }


    /** Returns the "title" attribute of this element, or null. */
    final public String getTitle ()
	{ return getAttribute ("title"); }

    /** Assigns the "title" attribute of this element. */
    final public void setTitle (String title)
	{ setAttribute ("title", title); }


    /**
     * Returns the "xml:lang" attribute of this element, or the value
     * of the "lang" attribute if there is none; searches parents for
     * such values, as appropriate.
     */
    public String getLang ()
    {
	String retval = getAttribute ("xml:lang");
	if (retval == null)
	    retval = getAttribute ("lang");
	if (retval != null)
	    return retval;
	
	Node parent = getParentNode ();
	if (parent == null || !(parent instanceof HTMLElement))
	    return null;
	return ((HTMLElement) parent).getLang ();
    }

    /**
     * Sets the "lang" and "xml:lang" attributes of this element.
     * These values must be in the standard IETF form for such langauge
     * identifiers; the value is not currently checked for errors.
     */
    final public void setLang (String lang)
    {
	setAttribute ("lang", lang);
	setAttribute ("xml:lang", lang);
    }

    /**
     * Returns the "dir" attribute of this element; searches parents
     * for such a value, as appropriate.
     */
    public String getDir ()
    {
	String retval = getAttribute ("dir");
	if (retval != null)
	    return retval;
	
	Node parent = getParentNode ();
	if (parent == null || !(parent instanceof HTMLElement))
	    return null;
	return ((HTMLElement) parent).getDir ();
    }

    /** Assigns the "dir" attribute of this element. */
    public void setDir (String dir)
    {
	// simple to test this for legality
	if ("ltr".equals (dir) || "rtl".equals (dir))
	    setAttribute ("dir", dir);
	else
	    throw new DomEx (DomEx.NOT_SUPPORTED_ERR, dir, null, 0);
    }


    /** Returns the name of the CSS "class" attribute of this element. */
    final public String getClassName ()
	{ return getAttribute ("class"); }

    /** Assigns the CSS "class" attribute of this element. */
    final public void setClassName (String className)
	{ setAttribute ("class", className); }

}
