//*****************************************************************************
/*
** FILE:   xg_ElementDecl.java
**
** (c) 1997 Steve Withall.
**
** HISTORY:
**    22Nov97  stevew  Created.
*/
package xg;

import xa.xa_Keyword;
import xa.xa_NodeTypeChoiceList;

import eh.eh_Debug;

import java.util.Vector;
import java.io.IOException;
import java.io.Writer;

//*****************************************************************************
/**
*  Class xg_ElementDecl - An element declaration, within a DTD.
*/
public class xg_ElementDecl extends xg_Node
{
    // Constants for the possible element declaration types.
    public final static int    EMPTY_TYPE    = 0;  // EMPTY
    public final static int    ANY_TYPE      = 1;  // ANY
    public final static int    MIXED_TYPE    = 2;  // Mixed
    public final static int    ELEMENTS_TYPE = 3;  // Element

    public final static String EMPTY_STRING  = "EMPTY";
    public final static String ANY_STRING    = "ANY";

    // Static data attributes.
    /** Vector of the valid element types. */
    private static Vector  TypeVector  = null;

    // Proper data attributes.
    protected int     NodeType         = 0;

    /** The name of this element. */
    protected String  AttName          = null;

    /** List of strings defining the possible values which this element may have. */
    protected Vector  AllowedValueList = null;

    /** Defines whether and how a default value is applied. The possible values are:
     *
     *    REQUIRED: This element must be present.
     *    IMPLIED:  This element may be omitted.
     *    FIXED:    If present, this element's value must equal the default.
     *    SIMPLE:   This element has a simple default value. */
    protected int     DefaultType      = ANY_TYPE;

    /** The default value of this element. */
    protected String  DefaultValue     = null;

    //*****************************************************************************
    /**
     * Construct an element declaration with no type and no name.
     */
    public xg_ElementDecl()
    {
        if (TypeVector == null)
            initialise();
    }

    //*****************************************************************************
    /**
     * Construct an element declaration with a name.
     *
     * @param  InputElementName  The name of the element
     */
    public xg_ElementDecl(String InputElementName)
    {
        super(InputElementName);
        if (TypeVector == null)
            initialise();
        AttName = InputElementName;
    }

    //*****************************************************************************
    /**
     * Save this element declaration (and its children) in XML source form
     * in InputWriter.
     *
     * @param  InputWriter   The writer to which the XML will be written
     */
    public void save(Writer  InputWriter) throws IOException
    {
        eh_Debug.add(7, "xg_ElementDecl.save: Save element decl '" + AttName + "'");  //TEMP
        InputWriter.write(PrecedingWhitespace);
        InputWriter.write(AttName);   // Save the element name

        switch (NodeType)
        {
            case EMPTY_TYPE:
                InputWriter.write(' '+ EMPTY_STRING + ' ');   // ' EMPTY '
                break;

            case ANY_TYPE:
                InputWriter.write(' '+ ANY_STRING + ' ');   // ' ANY '
                break;

            case MIXED_TYPE:
                // Save the list of allowed values (if there are any).
                InputWriter.write(' ' + xa_Keyword.OPEN_PAREN_CHAR);  // ' ('
                String  CurrentAllowedValue = null;
//TBD
/*                if (AllowedValueList != null)
                {
                    String   CurrentAllowedValue = null;
                    boolean  PrecedingValueFlag  = false;
                    for (int CurrentChildIndex = 0;
                             CurrentChildIndex < AllowedValueList.getChildCount();
                             CurrentChildIndex++)
                    {
                        if (PrecedingValueFlag)
                            InputWriter.write(xa_Keyword.OR_CHAR);  // '|'
                        else
                            PrecedingValueFlag = true;

                        CurrentAllowedValue = (String)AllowedValueList.elementAt(CurrentChildIndex);
                        InputWriter.write(CurrentAllowedValue);  // Save this allowed value
                    }
                }
*/
                InputWriter.write(xa_Keyword.CLOSE_PAREN_CHAR);  // ')'
                break;

            default:
                break;
        }

        InputWriter.write(xa_Keyword.TAG_END_CHAR);
    }

    //*****************************************************************************
    /**
     * Add an allowed value.
     *
     * @param  InputAllowedValue  The allowed value to be added
     */
    public void addAllowedValue(String  InputAllowedValue)
    {
        if (AllowedValueList == null)
            AllowedValueList = new Vector();

        AllowedValueList.addElement(InputAllowedValue);
    }

    //*****************************************************************************
    /**
     * Get the type of this node.
     *
     * @return  The type of this node
     */
    public int getType()
    {
        return xa_NodeTypeChoiceList.ELEMENT_DECL_TYPE;
    }

    //*****************************************************************************
    /**
     * Get the type of this node, using only type values defined for the DOM.
     * (Implements org.w3c.dom.Node.getNodeType.)
     *
     * @return  The DOM type of this node
     */
    public int getNodeType()
    {
        return -1;
    }

    //*****************************************************************************
    /**
     * Get the name of the element.
     *
     * @return  The name of the element
     */
    public String getName()
    {
        return AttName;
    }

    //*****************************************************************************
    /**
     * Return a string representation of the element declaration (intended for
     * use as debug output).
     *
     * @return  String representing the element type and its name.
     */
    public String toString()
    {
        return ("Element declaration '" + AttName + "', type " + NodeType);
    }

    //*****************************************************************************
    /**
     * Get the default type (ie. the type of defaulting) of the element.
     *
     * @return  The default type of the element
     */
    public int getDefaultType()
    {
        return DefaultType;
    }

    //*****************************************************************************
    /**
     * Get the default value of the element.
     *
     * @return  The default value of the element
     */
    public String getDefaultValue()
    {
        return DefaultValue;
    }

    //*****************************************************************************
    /**
     * Get the (integer) type of an element given a string representation of that
     * type.
     *
     * @param   InputTypeString  The string representation of of the element
     * @return                   The integer representation of of the element
     */
    static public int getType(String  InputTypeString)
    {
        return TypeVector.indexOf(InputTypeString);
    }

    //*****************************************************************************
    /**
     * Check if a value is allowed (ie. is on the list of allowed values).
     *
     * @param   InputValue  The value we are testing to see if it is allowed
     * @return  True if the InputValue is one of the allowed values; false if not.
     */
    public boolean isValueAllowed(String  InputValue)
    {
        return (    AllowedValueList != null
                 && AllowedValueList.indexOf(InputValue) != -1);
    }

    //*****************************************************************************
    /**
     * Set the name of this element.
     *
     * @param  InputAttName   The name of this element
     */
    public void setName(String  InputAttName)
    {
        AttName = InputAttName;
    }

    //*****************************************************************************
    /**
     * Set the type of this element from a string representation of the type.
     * The type is set to -1 if an unacceptable string is given.
     *
     * @param  InputElementType   The name of this element
     */
    public void setType(int  InputElementType)
    {
        NodeType = InputElementType;
    }
//    public int setType(String  InputTypeString)
//    {
//        NodeType = getType(InputTypeString);
//        return NodeType;
//    }

    //*****************************************************************************
    /**
     * Set the default type of this element.
     *
     * @param  InputDefaultType   The default type of this element
     */
    public void setDefaultType(int  InputDefaultType)
    {
        DefaultType = InputDefaultType;
    }

    //*****************************************************************************
    /**
     * Set the default value of this element.
     *
     * @param  InputDefaultValue   The default value of this element
     */
    public void setDefaultValue(String  InputDefaultValue)
    {
        DefaultValue = InputDefaultValue;
    }

    //*****************************************************************************
    /**
     * Initialise the vector of the allowed element types.
     */
    static private void initialise()
    {
        eh_Debug.add(7, "xg_ElementDecl.initialise:");
        TypeVector = new Vector();

        TypeVector.insertElementAt(EMPTY_STRING, EMPTY_TYPE);
        TypeVector.insertElementAt(ANY_STRING,   ANY_TYPE);
    }
}

//*****************************************************************************
