//*****************************************************************************
/*
** FILE:   xs_ElementElement.java
**
** (c) 1998 Steve Withall.
**
** HISTORY:
**    21Jun98  stevew  Created.
*/
package xs;

import xg.xg_Element;
import xg.xg_Node;
import xg.xg_VerificationException;

import eh.eh_Debug;

//*****************************************************************************
/** An 'element' element in an XSL pattern within an XSL rule, which plays an
 *  essentially passive role as an ancestor or descendant of a 'target-element'
 *  element.
 */
public class xs_ElementElement extends xs_PatternElement
{
    /** The name of the element type in the source to which this element
     *  matches. It may be null, in which case it will match *any* type of
     *  source element. */
    protected String           SourceTypeName      = null;

    /** We allow no more than one child of type xs_ElementElement. If there is
     *  one such child, this is it. */
    xs_ElementElement          ElementElementChild = null;

    /** The element type name normally used in XML for this sort of element. */
    public final static String RegisteredName      = "element";

    /** The name of the attribute which (if present) is used to identify the
     *  type of the element in the source document with which this pattern
     *  must match. */
    public final static String TypeAttName         = "type";

    //*****************************************************************************
    /** Construct an 'element' element with no name.
     */
    public xs_ElementElement()
    {
    }

    //*****************************************************************************
    /** Construct an 'element' element with a name.
     *
     *  @param  InputNodeName  The name of the element
     */
    public xs_ElementElement(String InputNodeName)
    {
        super(InputNodeName);
    }

    //*****************************************************************************
    /** <p>Verify that this node is correct (ie. internally correct and/or consistent
     *  with other nodes - such as its parent). The node is OK iff it has no more
     *  than one child which is an instance of xs_ElementElement.</p>
     *
     *  @exception  xg_VerificationException Description of verification problem
     */
    public void verify() throws xg_VerificationException
    {
        eh_Debug.add(8, "xs_ElementElement.verify: Verify '" + toString() + "'");

        // Run through all this rule's children, picking up the patterns and actions,
        // and checking there are no problems with them.
/*        xg_Node  CurrentChild    = null;
        boolean  ActionFoundFlag = false;  // Used to check if a pattern follows an action
        for (int ChildIndex = 0; ChildIndex < getChildCount(); ChildIndex++)
        {
            CurrentChild = (xg_Node)getChildAt(ChildIndex);
            if (CurrentChild.getNodeType() == xa_NodeTypeChoiceList.ELEMENT_TYPE)  // DOM type
            {
                if (CurrentChild instanceof xs_PatternElement)
                {
                    // A pattern cannot follow an action.
                    if (ActionFoundFlag)
                        throw new xg_VerificationException("'Pattern' follows an 'action' in XSL rule",
                                                           CurrentChild.getStartOffset(),
                                                           CurrentChild.getEndOffset() );

                    PatternVector.addElement(CurrentChild);

                    // If the child is of type 'root', then flag this as a root rule.
                    if (CurrentChild.getName().equals("root") )
                    {
                        // Make sure there is no more than one root pattern.
                        if (RootRuleFlag)
                            throw new xg_VerificationException("XSL rule contains more than one 'root' entry",
                                                               CurrentChild.getStartOffset(),
                                                               CurrentChild.getEndOffset() );
                        RootRuleFlag = true;
                    }
                }
                else
                {
                    // If it's not a pattern, then we treat it as an action!
                    ActionFoundFlag = true;
                    ActionVector.addElement(CurrentChild);
                }
            }
        }
*/
        calcMatchLevel();  // Calculate this element's pattern match level
        eh_Debug.add(6, "xs_ElementElement.verify: '" + NodeName
                               + "' has an overall match level of "
                               + MatchLevel.getOverallMatchLevel() );
    }

    //*****************************************************************************
    /** See if this pattern matches the InputSourceElement. If so, return true.
     *
     *  @param      InputSourceElement  The source node to match
     *  @return                         The best pattern after checking this one: it
     *                                   will either be InputBestPattern or this
     *  @exception  xs_StyleException   An error occurred
     */
    public boolean isMatch(xg_Element  InputSourceElement) throws xs_StyleException
    {
        eh_Debug.add(6, "xs_ElementElement.isMatch: Does pattern #" + PatternNumberString
                               + " match " + InputSourceElement + "?");

        //TBD This implementation is suitable for xs_TargetElementElement.
        //TBD In xs_ElementElement, we need to invoke isMatch() on the ElementElementChild.

        boolean  MatchFlag = true;
        // Check the InputSourceElement is of the correct type (if appropriate).
        if (    (SourceTypeName != null)
             && (!SourceTypeName.equals(InputSourceElement.getName() ) ) )
            MatchFlag = false;

        return MatchFlag;
    }

    //*****************************************************************************
    /** Calculate this pattern's match level, which includes figuring out the
     *  value of each of the match level's constituents.
     */
    public void calcMatchLevel()
    {
        // Get the type of element this XSL element applies to.
        SourceTypeName = getAttributeValue(TypeAttName);
        if (SourceTypeName != null)
            MatchLevel.incrementTypeElementCount(1);  // One more 'type' in this pattern

        addMatchLevelsOfChildren();
    }

    //*****************************************************************************
    /** Get the type of source element to which this element applies.
     *
     *  @return  the type of source element to which this element applies, which
     *            may be null
     */
    public String getSourceTypeName()
    {
        return SourceTypeName;
    }
}

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