All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ee.telekom.workflow.util.MethodUtil Maven / Gradle / Ivy

package ee.telekom.workflow.util;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.ClassUtils;

import ee.telekom.workflow.graph.WorkflowException;

public class MethodUtil{

    public static Class[] getArgumentClasses( Object[] arguments ){
        if( arguments == null || arguments.length == 0 ){
            return new Class[0];
        }
        else{
            Class[] argumentClasses = new Class[arguments.length];
            for( int i = 0; i < arguments.length; i++ ){
                argumentClasses[i] = arguments[i] == null ? null : arguments[i].getClass();
            }
            return argumentClasses;
        }
    }

    public static Method findMethod( Class clazz, String methodName, Class[] argumentClasses ) throws SecurityException{
        List candidates = new ArrayList<>();

        for( Method method : clazz.getMethods() ){
            if( !Modifier.isPublic( method.getModifiers() )
                    || !method.getName().equals( methodName )
                    || !hasAssignableArguments( method, argumentClasses, false ) ){
                continue;
            }
            candidates.add( method );
        }

        if( candidates.size() == 0 ){
            throw new WorkflowException( "No suitable method " + methodName
                    + " found on target of class " + clazz.getName()
                    + " with arguments " + Arrays.toString( argumentClasses ) );
        }
        else if( candidates.size() > 1 ){

            for( Method method : candidates ){
                if( hasAssignableArguments( method, argumentClasses, true ) ){
                    return method;
                }
            }

            throw new WorkflowException( "Multiple suitable methods " + methodName
                    + " found on target of class " + clazz.getName()
                    + " with arguments " + Arrays.toString( argumentClasses ) );
        }
        else{
            return candidates.get( 0 );
        }
    }

    private static boolean hasAssignableArguments( Method method, Class[] argumentClasses, boolean strict ){
        Class[] parameterClasses = method.getParameterTypes();
        if( parameterClasses.length == argumentClasses.length ){
            return hasAssignableArgumentsWithoutVarArgs( parameterClasses, argumentClasses, strict );
        }
        else if( method.isVarArgs() ){
            return hasAssignableArgumentsWithVarArgs( parameterClasses, argumentClasses, strict );
        }
        return false;
    }

    private static boolean hasAssignableArgumentsWithoutVarArgs( Class[] parameterClasses, Class[] argumentClasses, boolean strict ){
        for( int i = 0; i < argumentClasses.length; i++ ){
            if( argumentClasses[i] != null ){
                if( !isAssignable( parameterClasses[i], argumentClasses[i], strict ) ){
                    return false;
                }
            }
        }
        return true;
    }

    private static boolean hasAssignableArgumentsWithVarArgs( Class[] parameterClasses, Class[] argumentClasses, boolean strict ){
        for( int i = 0; i < parameterClasses.length - 1; i++ ){
            if( argumentClasses[i] != null ){
                if( !isAssignable( parameterClasses[i], argumentClasses[i], strict ) ){
                    return false;
                }
            }
        }
        Class varArgArrayComponentType = parameterClasses[parameterClasses.length - 1].getComponentType();
        for( int i = parameterClasses.length; i < argumentClasses.length; i++ ){
            if( !isAssignable( varArgArrayComponentType, argumentClasses[i], strict ) ){
                return false;
            }
        }
        return true;
    }

    private static boolean isAssignable( Class parameterClass, Class argumentClass, boolean strict ){
        return strict ? parameterClass.equals( argumentClass ) : ClassUtils.isAssignable( argumentClass, parameterClass, !strict );
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy