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

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

import xa.xa_NodeTypeChoiceList;

import eh.eh_Debug;

import java.util.Vector;

//*****************************************************************************
/** An XML element to represent a 'style-rule' element in an XSL stylesheet.
*/
public class xs_StyleRuleElement extends xs_RuleElement
{
    /** Is this a (the!) root rule? */
//    protected boolean          RootRuleFlag = false;

    /** Vector of this rule's patterns. A child is treated as a pattern if it is
     *  an instance of xs_PatternElement. */
//    protected Vector           PatternVector  = new Vector();

    /** <p>Vector of this rule's actions. All of the rule's child elements (that
     *  is, excluding comments, PIs, etc.) after the patterns are treated as actions.
     *  They may be derived from xs_ActionElement (in which case they will be
     *  treated specially), but they may simply be normal xg_Element objects.</p>
     *
     *  <p>Note that we can support multiple actions in a single rule, whereas
     *  it would appear that XSL intends to allow only one.</p> */
//    protected Vector           ActionVector   = new Vector();

    /** This style rule's number. Each style rule is given a sequential number
     *  during XML parsing of the stylesheet, to make it easier to identify.
     *  This is for convenience only, and plays no part whatsoever in the XSL
     *  processing itself. */
    protected int              StyleRuleNumber   = 0;

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

    /** The name of the attribute used to identify the importance of this rule. */
//    public final static String ImportanceAttName = "importance";

    /** The name of the attribute used to identify the priority of this rule. */
//    public final static String PriorityAttName   = "priority";

    //*****************************************************************************
    /** Construct an XSL rule element with no type and no name.
     */
    public xs_StyleRuleElement()
    {
    }

    //*****************************************************************************
    /** Construct an XSL rule element with a name.
     *
     *  @param  InputNodeName  The name of the element
     */
    public xs_StyleRuleElement(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 must have one or more
     *  xs_PatternElement children, followed by one or more action children (which
     *  may be xs_ActionElement or plain xg_Element objects). The node may have
     *  a 'root' action - but not more than one.</p>
     *
     *  @exception  xg_VerificationException  Description of verification problem
     */
/*    public void verify() throws xg_VerificationException
    {
        eh_Debug.add(8, "xs_StyleRuleElement.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);
                }
            }
        }
    }
*/
    //*****************************************************************************
    /** See if any of this rule's patterns match the InputSourceNode, and are a
     *  better match than the InputBestPattern (which may be null).
     *
     *  @param      InputBestPattern    The best pattern found in previous rules
     *                                   (or null if no match has so far been found)
     *  @param      InputSourceElement  The source element to match
     *  @return                         The best pattern after checking this rule: it
     *                                   will either be InputBestPattern or one of
     *                                   this rule's patterns
     *  @exception  xs_StyleException   An error occurred processing the actions
     */
/*    public xs_PatternElement matchPattern(xs_PatternElement  InputBestPattern,
                                          xg_Element         InputSourceElement)
                                                throws xs_StyleException
    {
        eh_Debug.add(6, "xs_StyleRuleElement.matchPattern: Does rule #" + StyleRuleNumber
                              + " contain the best pattern for " + InputSourceElement + "?");
        xs_PatternElement  CurrentPattern   = null;
        xs_PatternElement  BestPattern      = InputBestPattern;
        boolean            NewBestMatchFlag = false;
        for (int PatternIndex = 0; PatternIndex < PatternVector.size(); PatternIndex++)
        {
            CurrentPattern   = (xs_PatternElement)PatternVector.elementAt(PatternIndex);
            NewBestMatchFlag = CurrentPattern.isBestMatch(BestPattern,
                                                          InputSourceElement);
            if (NewBestMatchFlag)
            {
                // This pattern is a match, and a better match than before.
                BestPattern = CurrentPattern;
            }
        }

        return BestPattern;
    }
*/
    //*****************************************************************************
    /** Invoke this rule's actions on the given source node.
     *
     *  @param      InputSourceNode    The source node
     *  @exception  xs_StyleException  An error occurred processing the actions
     */
/*    public void invokeActions(xg_Node  InputSourceNode) throws xs_StyleException
    {
        eh_Debug.add(6, "xs_StyleRuleElement.invokeActions: on '" + toString() + "'");
    }
*/
    //*****************************************************************************
    /** Set this rule's sequential number. Also set the number of each of this rule's
     *  patterns.
     *
     *  @param  InputRuleNumber  The sequential number given to this rule
     */
    public void setRuleNumber(int  InputRuleNumber)
    {
        StyleRuleNumber = InputRuleNumber;

        // Set the number of each child pattern.
        xs_PatternElement  CurrentPattern = null;
        for (int PatternIndex = 0; PatternIndex < PatternVector.size(); PatternIndex++)
        {
            CurrentPattern = (xs_PatternElement)PatternVector.elementAt(PatternIndex);
            CurrentPattern.setRuleNumber(InputRuleNumber, (PatternIndex + 1) );
        }
    }

    //*****************************************************************************
    /** Get the vector of this rule's patterns.
     *
     *  @return  The vector of patterns
     */
/*    public Vector getPatterns()
    {
        return PatternVector;
    }
*/
    //*****************************************************************************
    /** Get the vector of this rule's actions.
     *
     *  @return  The vector of actions
     */
/*    public Vector getActions()
    {
        return ActionVector;
    }
*/
    //*****************************************************************************
    /** Get this rule's sequential number (which must be set manually via an
     *  external call to setRuleNumber() ).
     *
     *  @return  The sequential number given to this rule
     */
    public int getRuleNumber()
    {
        return StyleRuleNumber;
    }

    //*****************************************************************************
    /** Return a string representation of the element (intended for use as debug
     *  output).
     *
     *  @return  String represention of the node.
     */
    public String toString()
    {
        StringBuffer  SummaryStringBuffer = new StringBuffer();
        if (PatternVector.size() == 0)
            SummaryStringBuffer.append("XSL default style rule");
        else
            SummaryStringBuffer.append("XSL style rule");

        if (StyleRuleNumber > 0)
            SummaryStringBuffer.append(" (#" + StyleRuleNumber + ")");
        return (SummaryStringBuffer.toString() );
    }
}

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