public void end()

in commons-digester3-core/src/main/java/org/apache/commons/digester3/CallMethodRule.java [308:434]


    public void end( final String namespace, final 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 };
        }
        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.
        final 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() )
        {
            final 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;
        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 );
    }