package org.apache.commons.digester3;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import static java.lang.System.arraycopy;
import static java.lang.String.format;
import static java.util.Arrays.fill;
import static org.apache.commons.beanutils.ConvertUtils.convert;
import static org.apache.commons.beanutils.MethodUtils.invokeExactMethod;
import static org.apache.commons.beanutils.MethodUtils.invokeMethod;

import java.util.Formatter;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * <p>
 * Rule implementation that calls a method on an object on the stack (normally the top/parent object), passing arguments
 * collected from subsequent <code>CallParamRule</code> rules or from the body of this element.
 * </p>
 * <p>
 * By using {@link #CallMethodRule(String methodName)} a method call can be made to a method which accepts no arguments.
 * </p>
 * <p>
 * Incompatible method parameter types are converted using <code>org.apache.commons.beanutils.ConvertUtils</code>.
 * </p>
 * <p>
 * This rule now uses {@link org.apache.commons.beanutils.MethodUtils#invokeMethod} by default.
 * This increases the kinds of methods successfully and allows primitives to be matched by passing in wrapper classes.
 * There are rare cases when {@link org.apache.commons.beanutils.MethodUtils#invokeExactMethod} (the old default) is
 * required. This method is much stricter in it's reflection.
 * Setting the <code>UseExactMatch</code> to true reverts to the use of this method.
 * </p>
 * <p>
 * Note that the target method is invoked when the <i>end</i> of the tag the CallMethodRule fired on is encountered,
 * <i>not</i> when the last parameter becomes available. This implies that rules which fire on tags nested within the
 * one associated with the CallMethodRule will fire before the CallMethodRule invokes the target method. This behavior
 * is not configurable.
 * </p>
 * <p>
 * Note also that if a CallMethodRule is expecting exactly one parameter and that parameter is not available (eg
 * CallParamRule is used with an attribute name but the attribute does not exist) then the method will not be invoked.
 * If a CallMethodRule is expecting more than one parameter, then it is always invoked, regardless of whether the
 * parameters were available or not; missing parameters are converted to the appropriate target type by calling
 * ConvertUtils.convert. Note that the default ConvertUtils converters for the String type returns a null when passed a
 * null, meaning that CallMethodRule will passed null for all String parameters for which there is no parameter info
 * available from the XML. However parameters of type Float and Integer will be passed a real object containing a zero
 * value as that is the output of the default ConvertUtils converters for those types when passed a null. You can
 * register custom converters to change this behavior; see the BeanUtils library documentation for more info.
 * </p>
 * <p>
 * Note that when a constructor is used with paramCount=0, indicating that the body of the element is to be passed to
 * the target method, an empty element will cause an <i>empty string</i> to be passed to the target method, not null.
 * And if automatic type conversion is being applied (ie if the target function takes something other than a string as a
 * parameter) then the conversion will fail if the converter class does not accept an empty string as valid input.
 * </p>
 * <p>
 * CallMethodRule has a design flaw which can cause it to fail under certain rule configurations. All CallMethodRule
 * instances share a single parameter stack, and all CallParamRule instances simply store their data into the
 * parameter-info structure that is on the top of the stack. This means that two CallMethodRule instances cannot be
 * associated with the same pattern without getting scrambled parameter data. This same issue also applies when a
 * CallMethodRule matches some element X, a different CallMethodRule matches a child element Y and some of the
 * CallParamRules associated with the first CallMethodRule match element Y or one of its child elements. This issue has
 * been present since the very first release of Digester. Note, however, that this configuration of CallMethodRule
 * instances is not commonly required.
 * </p>
 */
public class CallMethodRule
    extends Rule
{

    // ----------------------------------------------------------- Constructors

    /**
     * Construct a "call method" rule with the specified method name. The parameter types (if any) default to
     * java.lang.String.
     *
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of this
     *            element.
     */
    public CallMethodRule( String methodName, int paramCount )
    {
        this( 0, methodName, paramCount );
    }

    /**
     * Construct a "call method" rule with the specified method name. The parameter types (if any) default to
     * java.lang.String.
     *
     * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester
     *            object stack. Negative numbers are relative to the bottom of the stack. Zero implies the top object on
     *            the stack.
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of this
     *            element.
     */
    public CallMethodRule( int targetOffset, String methodName, int paramCount )
    {
        this.targetOffset = targetOffset;
        this.methodName = methodName;
        this.paramCount = paramCount;
        if ( paramCount == 0 )
        {
            this.paramTypes = new Class[] { String.class };
        }
        else
        {
            this.paramTypes = new Class[paramCount];
            fill( this.paramTypes, String.class );
        }
    }

    /**
     * Construct a "call method" rule with the specified method name. The method should accept no parameters.
     *
     * @param methodName Method name of the parent method to call
     */
    public CallMethodRule( String methodName )
    {
        this( 0, methodName, 0, (Class[]) null );
    }

    /**
     * Construct a "call method" rule with the specified method name. The method should accept no parameters.
     *
     * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester
     *            object stack. Negative numbers are relative to the bottom of the stack. Zero implies the top object on
     *            the stack.
     * @param methodName Method name of the parent method to call
     */
    public CallMethodRule( int targetOffset, String methodName )
    {
        this( targetOffset, methodName, 0, (Class[]) null );
    }

    /**
     * Construct a "call method" rule with the specified method name and parameter types. If <code>paramCount</code> is
     * set to zero the rule will use the body of this element as the single argument of the method, unless
     * <code>paramTypes</code> is null or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of ths element
     * @param paramTypes The Java class names of the arguments (if you wish to use a primitive type, specify the
     *            corresonding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
     *            <code>boolean</code> parameter)
     */
    public CallMethodRule( String methodName, int paramCount, String[] paramTypes )
    {
        this( 0, methodName, paramCount, paramTypes );
    }

    /**
     * Construct a "call method" rule with the specified method name and parameter types. If <code>paramCount</code> is
     * set to zero the rule will use the body of this element as the single argument of the method, unless
     * <code>paramTypes</code> is null or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester
     *            object stack. Negative numbers are relative to the bottom of the stack. Zero implies the top object on
     *            the stack.
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of the element
     * @param paramTypes The Java class names of the arguments (if you wish to use a primitive type, specify the
     *            corresponding Java wrapper class instead, such as <code>java.lang.Boolean</code> for a
     *            <code>boolean</code> parameter)
     */
    public CallMethodRule( int targetOffset, String methodName, int paramCount, String[] paramTypes )
    {
        this.targetOffset = targetOffset;
        this.methodName = methodName;
        this.paramCount = paramCount;
        if ( paramTypes == null )
        {
            this.paramTypes = new Class[paramCount];
            fill( this.paramTypes, String.class );
        }
        else
        {
            // copy the parameter class names into an array
            // the classes will be loaded when the digester is set
            this.paramClassNames = new String[paramTypes.length];
            arraycopy( paramTypes, 0, this.paramClassNames, 0, paramTypes.length );
        }
    }

    /**
     * Construct a "call method" rule with the specified method name and parameter types. If <code>paramCount</code> is
     * set to zero the rule will use the body of this element as the single argument of the method, unless
     * <code>paramTypes</code> is null or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of the element
     * @param paramTypes The Java classes that represent the parameter types of the method arguments (if you wish to use
     *            a primitive type, specify the corresponding Java wrapper class instead, such as
     *            <code>java.lang.Boolean.TYPE</code> for a <code>boolean</code> parameter)
     */
    public CallMethodRule( String methodName, int paramCount, Class<?> paramTypes[] )
    {
        this( 0, methodName, paramCount, paramTypes );
    }

    /**
     * Construct a "call method" rule with the specified method name and parameter types. If <code>paramCount</code> is
     * set to zero the rule will use the body of this element as the single argument of the method, unless
     * <code>paramTypes</code> is null or empty, in this case the rule will call the specified method with no arguments.
     *
     * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester
     *            object stack. Negative numbers are relative to the bottom of the stack. Zero implies the top object on
     *            the stack.
     * @param methodName Method name of the parent method to call
     * @param paramCount The number of parameters to collect, or zero for a single argument from the body of the element
     * @param paramTypes The Java classes that represent the parameter types of the method arguments (if you wish to use
     *            a primitive type, specify the corresponding Java wrapper class instead, such as
     *            <code>java.lang.Boolean.TYPE</code> for a <code>boolean</code> parameter)
     */
    public CallMethodRule( int targetOffset, String methodName, int paramCount, Class<?>[] paramTypes )
    {
        this.targetOffset = targetOffset;
        this.methodName = methodName;
        this.paramCount = paramCount;
        if ( paramTypes == null )
        {
            this.paramTypes = new Class<?>[paramCount];
            fill( this.paramTypes, String.class );
        }
        else
        {
            this.paramTypes = new Class<?>[paramTypes.length];
            arraycopy( paramTypes, 0, this.paramTypes, 0, paramTypes.length );
        }
    }

    // ----------------------------------------------------- Instance Variables

    /**
     * The body text collected from this element.
     */
    protected String bodyText = null;

    /**
     * location of the target object for the call, relative to the top of the digester object stack. The default value
     * of zero means the target object is the one on top of the stack.
     */
    protected int targetOffset = 0;

    /**
     * The method name to call on the parent object.
     */
    protected String methodName = null;

    /**
     * The number of parameters to collect from <code>MethodParam</code> rules. If this value is zero, a single
     * parameter will be collected from the body of this element.
     */
    protected int paramCount = 0;

    /**
     * The parameter types of the parameters to be collected.
     */
    protected Class<?>[] paramTypes = null;

    /**
     * The names of the classes of the parameters to be collected. This attribute allows creation of the classes to be
     * postponed until the digester is set.
     */
    private String[] paramClassNames = null;

    /**
     * Should <code>MethodUtils.invokeExactMethod</code> be used for reflection.
     */
    private boolean useExactMatch = false;

    // --------------------------------------------------------- Public Methods

    /**
     * Should <code>MethodUtils.invokeExactMethod</code> be used for the reflection.
     *
     * @return true, if <code>MethodUtils.invokeExactMethod</code> Should be used for the reflection,
     *         false otherwise
     */
    public boolean getUseExactMatch()
    {
        return useExactMatch;
    }

    /**
     * Set whether <code>MethodUtils.invokeExactMethod</code> should be used for the reflection.
     *
     * @param useExactMatch The <code>MethodUtils.invokeExactMethod</code> flag
     */
    public void setUseExactMatch( boolean useExactMatch )
    {
        this.useExactMatch = useExactMatch;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setDigester( Digester digester )
    {
        // call superclass
        super.setDigester( digester );
        // if necessary, load parameter classes
        if ( this.paramClassNames != null )
        {
            this.paramTypes = new Class<?>[paramClassNames.length];
            for ( int i = 0; i < this.paramClassNames.length; i++ )
            {
                try
                {
                    this.paramTypes[i] = digester.getClassLoader().loadClass( this.paramClassNames[i] );
                }
                catch ( ClassNotFoundException e )
                {
                    throw new RuntimeException( format( "[CallMethodRule] Cannot load class %s at position %s",
                                                        this.paramClassNames[i], i ), e );
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void begin( String namespace, String name, Attributes attributes )
        throws Exception
    {
        // Push an array to capture the parameter values if necessary
        if ( paramCount > 0 )
        {
            Object parameters[] = new Object[paramCount];
            fill( parameters, null );
            getDigester().pushParams( parameters );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void body( String namespace, String name, String text )
        throws Exception
    {
        if ( paramCount == 0 )
        {
            this.bodyText = text.trim();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void end( String namespace, String name )
        throws Exception
    {
        // Retrieve or construct the parameter values array
        Object[] parameters;
        if ( paramCount > 0 )
        {
            parameters = getDigester().popParams();

            if ( getDigester().getLogger().isTraceEnabled() )
            {
                for ( int i = 0, size = parameters.length; i < size; i++ )
                {
                    getDigester().getLogger().trace( format( "[CallMethodRule]{%s} parameters[%s]=%s",
                                                             getDigester().getMatch(),
                                                             i,
                                                             parameters[i] ) );
                }
            }

            // In the case where the target method takes a single parameter
            // and that parameter does not exist (the CallParamRule never
            // executed or the CallParamRule was intended to set the parameter
            // from an attribute but the attribute wasn't present etc) then
            // skip the method call.
            //
            // This is useful when a class has a "default" value that should
            // only be overridden if data is present in the XML. I don't
            // know why this should only apply to methods taking *one*
            // parameter, but it always has been so we can't change it now.
            if ( paramCount == 1 && parameters[0] == null )
            {
                return;
            }

        }
        else if ( paramTypes != null && paramTypes.length != 0 )
        {
            // Having paramCount == 0 and paramTypes.length == 1 indicates
            // that we have the special case where the target method has one
            // parameter being the body text of the current element.

            // There is no body text included in the source XML file,
            // so skip the method call
            if ( bodyText == null )
            {
                return;
            }

            parameters = new Object[] { bodyText };
            if ( paramTypes.length == 0 )
            {
                paramTypes = new Class[] { String.class };
            }
        }
        else
        {
            // When paramCount is zero and paramTypes.length is zero it
            // means that we truly are calling a method with no parameters.
            // Nothing special needs to be done here.
            parameters = new Object[0];
            paramTypes = new Class<?>[0];
        }

        // Construct the parameter values array we will need
        // We only do the conversion if the param value is a String and
        // the specified paramType is not String.
        Object[] paramValues = new Object[paramTypes.length];
        for ( int i = 0; i < paramTypes.length; i++ )
        {
            // convert nulls and convert stringy parameters
            // for non-stringy param types
            if ( parameters[i] == null
                || ( parameters[i] instanceof String && !String.class.isAssignableFrom( paramTypes[i] ) ) )
            {
                paramValues[i] = convert( (String) parameters[i], paramTypes[i] );
            }
            else
            {
                paramValues[i] = parameters[i];
            }
        }

        // Determine the target object for the method call
        Object target;
        if ( targetOffset >= 0 )
        {
            target = getDigester().peek( targetOffset );
        }
        else
        {
            target = getDigester().peek( getDigester().getCount() + targetOffset );
        }

        if ( target == null )
        {
            throw new SAXException( format( "[CallMethodRule]{%s} Call target is null (targetOffset=%s, stackdepth=%s)",
                                            getDigester().getMatch(), targetOffset, getDigester().getCount() ) );
        }

        // Invoke the required method on the top object
        if ( getDigester().getLogger().isDebugEnabled() )
        {
            Formatter formatter =
                new Formatter().format( "[CallMethodRule]{%s} Call %s.%s(",
                                        getDigester().getMatch(),
                                        target.getClass().getName(),
                                        methodName );
            for ( int i = 0; i < paramValues.length; i++ )
            {
                formatter.format( "%s%s/%s", ( i > 0 ? ", " : "" ), paramValues[i], paramTypes[i].getName() );
            }
            formatter.format( ")" );
            getDigester().getLogger().debug( formatter.toString() );
        }

        Object result = null;
        if ( useExactMatch )
        {
            // invoke using exact match
            result = invokeExactMethod( target, methodName, paramValues, paramTypes );

        }
        else
        {
            // invoke using fuzzier match
            result = invokeMethod( target, methodName, paramValues, paramTypes );
        }

        processMethodCallResult( result );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void finish()
        throws Exception
    {
        bodyText = null;
    }

    /**
     * Subclasses may override this method to perform additional processing of the invoked method's result.
     *
     * @param result the Object returned by the method invoked, possibly null
     */
    protected void processMethodCallResult( Object result )
    {
        // do nothing
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString()
    {
        Formatter formatter = new Formatter().format( "CallMethodRule[methodName=%s, paramCount=%s, paramTypes={",
                                                      methodName, paramCount );
        if ( paramTypes != null )
        {
            for ( int i = 0; i < paramTypes.length; i++ )
            {
                formatter.format( "%s%s",
                                  ( i > 0 ? ", " : "" ),
                                  ( paramTypes[i] != null ? paramTypes[i].getName() : "null" ) );
            }
        }
        formatter.format( "}]" );
        return ( formatter.toString() );
    }

}
