/*
 * (C) Copyright IBM Corp. 1997-1998  All rights reserved.
 *
 * US Government Users Restricted Rights Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *
 * The program is provided "as is" without any warranty express or
 * implied, including the warranty of non-infringement and the implied
 * warranties of merchantibility and fitness for a particular purpose.
 * IBM will not be liable for any damages suffered by you as a result
 * of using the Program. In no event will IBM be liable for any
 * special, indirect or consequential damages or lost profits even if
 * IBM has been advised of the possibility of their occurrence. IBM
 * will not be liable for any third party claims against you.
 */

package com.ibm.xml.parser;

import java.util.*;

/**
 * The Attlist class provides services in support of DTD attribute list declarations.
 * <p>We will use the following example to illustrate the capabilities of attribute lists
 * within a <var>PERSON</var> Element:
 * <pre>
 * &lt;!ATTLIST PERSON
 *   EMPLOYEETYPE CDATA &quot;PERMANENT&quot;
 *   LASTNAME CDATA #REQUIRED
 *   PHONE ENTITY #IMPLIED
 *   COMPANY CDATA #FIXED &quot;IBM&quot; &gt;
 * </pre>
 * <p>In this example, the attributes <code>EMPLOYEETYPE</code> and <code>COMPANY</code> have
 * been assigned default values; <code>EMPLOYEETYPE</code>'s default value may be changed, but
 * <code>COMPANY</code>'s value is fixed and may not be changed.
 * <p>The <code>LASTNAME</code> attribute must be specified with each <code>PERSON</code> Element
 * because this attribute is defined as <code>REQUIRED</code>.
 * <p>Just because an attribute is not defined by the attribute list definition, it does not
 * mean that the attribute can not be defined in the document.  These attributes are known
 * as <code>IMPLIED</code> attributes.  However, you will need to explicitly define <code>IMPLIED</code>
 * attributes if you want them to have a value type other than <code>CDATA</code>.
 * <p>Value types are defined as follows:
 * <dl compact>
 * <dt>CDATA
 * <dd>A string-type attribute that can take any literal string as its value.
 * <dt>ID
 * <dd>An unique identifier for an Element within a given XML document.
 * <dt>IDREF
 * <dd>A pointer to an Element's ID within a given XML document.
 * <dt>IDREFS
 * <dd>Same as <code>IDREF</code> except multiple pointers may be provided.
 * <dt>ENTITY
 * <dd>A pointer to an external binary general entity (see Entity for details) defined
 * in this DTD.
 * <dt>ENTITIES
 * <dd>Same as <code>ENTITY</code> except multiple pointers may be provided.
 * <dt>NMTOKEN
 * <dd>Also known as a name token.  This is any mixture of name characters.
 * <dt>NMTOKENS
 * <dd>Same as <code>NMTOKEN</code> except multiple names may be provided.
 * <dt>NOTATION
 * <dd>A set of notations (see TXNotation for details) that are declared in this DTD.
 * <dt>NAME_TOKEN_GROUP
 * <dd>A set of <code>NMTOKEN</code> tokens.
 * </dl>
 *
 * @version 1.1
 * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
 * @see com.ibm.xml.parser.AttDef
 * @see com.ibm.xml.parser.Child
 * @see com.ibm.xml.parser.Entity
 * @see com.ibm.xml.parser.ExternalID
 * @see com.ibm.xml.parser.TXNotation
 */
public class Attlist extends Child {

            String  name    =   null;
            Vector  attDefs =   new Vector();

    /**
     * Constructor.
     * @param name      This attribute list's name; this value is also known as the Element type.
     */
    public Attlist(String name) {
        this.name = name;
    }

    /**
     * Clone this attribute list Node and its children (AttDefs) using the appropriate factory.
     * @return          Cloned attribute list Node.
     */
    public synchronized Object clone() {
        checkFactory();
        Attlist al = factory.createAttlist(this.name);
        al.setFactory(getFactory());
        al.attDefs.ensureCapacity(size());
        for (int i = 0;  i < size();  i ++)
            al.addElement((AttDef)((AttDef)this.attDefs.elementAt(i)).clone());
        return al;
    }
    
    /**
     * Returns that this object is an attribute list Node.
     * <p>This method is defined by DOM.
     * @return          Element Node indicator.
     */
    public int getNodeType() {                  
        return Child.ATTLIST;
    }
    
    /**
     * Returns this attribute list's name; this value is also known as the Element type.  
     * @return          The string that is this attribute list's name, or <var>null</var> if no name. 
     */
    public String getName() {
        return this.name;
    }

    /**
     * Adds the specified attribute definition to the end of this attribute list .
     * @param attDef    Attribute definition to add to this atribute list.
     * @return          =true if the attribute definition does not already exist in this
     *                  attribute list; otherwise, =false.
     * @see #elementAt
     * @see #getAttDef
     * @see #contains
     * @see #size
     */
    public boolean addElement(AttDef attDef) {
        if (contains(attDef.getName()))
            return false;
        this.attDefs.addElement(attDef);
        attDef.setParent(this);
        return true;
    }
    
    /**
     * Returns the attribute definition at the specified <var>index</var> in this attribute list 
     * @param index     Index into this list of attribute definitions.
     * @return          Attribute definition at the specified index, or <var>null</var> if an invalid index.           
     * @see #addElement
     * @see #getAttDef
     * @see #contains
     * @see #size
     */
    public AttDef elementAt(int index) {
        return (AttDef)this.attDefs.elementAt(index);
    }

    /**
     * Returns the attribute definition that matches the specified attribute definition name 
     * in this attribute list.
     * @param attDefName    Attribute definition name to match in this attribute list.
     * @return              The matching attribute definition, or <var>null</var> if the 
     *                      attribute is not currently defined.
     * @see #addElement
     * @see #elementAt
     * @see #contains
     * @see #size
     * @see #elements
     */
    public AttDef getAttDef(String attDefName) {
        for (int i = 0;  i < size();  i ++) {
            AttDef ad = elementAt(i);
            if (attDefName.equals(ad.getName()))
                return ad;
        }
        return null;
    }
    
    /**
     * Returns whether the specified attribute definition name is currently defined in this
     * attribute list.
     * @param attDefName    Attribute definition name to match in this attribute list.
     * @return              =true if <var>attDefName</var> is defined; otherwise, =false.           
     * @see #addElement
     * @see #elementAt
     * @see #getAttDef
     * @see #size
     * @see #elements
     */
    public boolean contains(String attDefName) {
        return null != getAttDef(attDefName);
    }
    
    /**
     * Returns the number of attribute definitions in this attribute list. 
     * @return          Number of attribute list definitions, or <var>null</var> if no 
     *                  definitions defined.           
     * @see #addElement
     * @see #elementAt
     * @see #getAttDef
     * @see #contains
     */
    public int size() {
        return this.attDefs.size();
    }
    
    /**
     * Returns an enumeration of all attribute definitions in this attribute list.
     * @return          An enumeration of all attribute definitions, or <var>null</var> if none specified.
     * @see #addElement
     * @see #elementAt
     * @see #getAttDef
     * @see #contains
     * @see #size
     */
    public Enumeration elements() {
        return this.attDefs.elements();
    }
    
}
