Java Method Call invoke(Object object, String function, Object... params)

Here you can find the source of invoke(Object object, String function, Object... params)

Description

Dynamically invokes the specified function on an object with the given parameters.

License

Open Source License

Parameter

Parameter Description
object the object to invoke on
function the function to call
params the parameters of the function

Return

the result of the invocation

Declaration

public static Object invoke(Object object, String function, Object... params) 

Method Source Code

//package com.java2s;
/*/*  w w  w. ja v  a2s  .  co  m*/
 * DuDe - The Duplicate Detection Toolkit
 * 
 * Copyright (C) 2010  Hasso-Plattner-Institut f?r Softwaresystemtechnik GmbH,
 *                     Potsdam, Germany 
 *
 * This file is part of DuDe.
 * 
 * DuDe is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * DuDe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with DuDe.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.Arrays;
import java.util.HashMap;

import java.util.Map;
import java.util.Map.Entry;

public class Main {
    /**
     * Dynamically invokes the specified function on an object with the given parameters.
     * 
     * @param object
     *            the object to invoke on
     * @param function
     *            the function to call
     * @param params
     *            the parameters of the function
     * @return the result of the invocation
     */
    public static Object invoke(Object object, String function, Object... params) {
        Class<? extends Object> type = object.getClass();
        try {
            Map<Method, Integer> candidateDistances = getCompatibleMethods(type, function, params);

            if (candidateDistances.isEmpty())
                throw new IllegalArgumentException(
                        String.format("no suitable method found in %s for name %s and parameters %s", type,
                                function, Arrays.toString(params)));

            if (candidateDistances.size() == 1)
                return invoke(candidateDistances.keySet().iterator().next(), object, params);

            Method bestMethod = pickBest(candidateDistances);
            if (bestMethod == null)
                throw new IllegalArgumentException(
                        String.format("more than one suitable method found in %s for name %s and parameters %",
                                type, function, Arrays.toString(params)));
            return invoke(bestMethod, object, params);
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    String.format("Could not invoke method %s for type %s with parameters %s", function, type,
                            Arrays.toString(params)),
                    e);
        }
    }

    private static Object invoke(Method method, Object object, Object[] params)
            throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        method.setAccessible(true);
        return method.invoke(object, params);
    }

    private static <T> Map<Method, Integer> getCompatibleMethods(Class<T> type, String name, Object... params) {
        Method[] methods = type.getDeclaredMethods();
        Map<Method, Integer> candidateDistances = new HashMap<Method, Integer>();
        for (Method method : methods) {
            if (!method.getName().equals(name))
                continue;

            int distance = 0;
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (params.length != parameterTypes.length)
                continue;

            for (int index = 0; index < parameterTypes.length; index++) {
                if (!parameterTypes[index].isInstance(params[index])) {
                    distance = Integer.MAX_VALUE;
                    break;
                }

                if (params[index] != null)
                    distance += getDistance(parameterTypes[index], params[index].getClass());
            }
            candidateDistances.put(method, distance);
        }
        if (type.getSuperclass() != null)
            candidateDistances.putAll(getCompatibleMethods(type.getSuperclass(), name, params));
        return candidateDistances;
    }

    private static <T> T pickBest(Map<T, Integer> candidateDistances) {
        int minDistance = Integer.MAX_VALUE;
        int minCount = 0;
        T minConstructor = null;
        for (Entry<T, Integer> entry : candidateDistances.entrySet())
            if (entry.getValue() < minDistance) {
                minDistance = entry.getValue();
                minConstructor = entry.getKey();
                minCount = 1;
            } else if (entry.getValue() == minDistance) {
                minCount++;
            }

        return minCount == 1 ? minConstructor : null;
    }

    private static int getDistance(Class<?> superClass, Class<?> subclass) {
        if (superClass == subclass)
            return 0;
        if (!superClass.isAssignableFrom(subclass))
            return Integer.MAX_VALUE;

        if (superClass.isInterface()) {
            Class<?>[] interfaces = subclass.getInterfaces();
            int minDistance = Integer.MAX_VALUE;
            for (Class<?> xface : interfaces) {
                if (xface == superClass) {
                    minDistance = 1;
                    break;
                } else if (superClass.isAssignableFrom(xface))
                    minDistance = Math.min(minDistance, getDistance(superClass, xface));
            }
        }

        int distance = 1;
        for (Class<?> klazz = subclass; superClass != klazz; distance++)
            klazz = klazz.getSuperclass();
        return distance;
    }
}

Related

  1. invoke(Object obj, String methodName, Object... params)
  2. invoke(Object obj, String methodName, Object[] params)
  3. invoke(Object obj, String name, Object... args)
  4. invoke(Object object, Method method)
  5. invoke(Object object, Object[] args, String methodName)
  6. invoke(Object object, String function, String parameter)
  7. invoke(Object object, String method, Object... args)
  8. invoke(Object object, String methodName)
  9. invoke(Object object, String methodName, Class[] argTypes, Object... args)