Here you can find the source of invoke(Object object, String function, Object... params)
Parameter | Description |
---|---|
object | the object to invoke on |
function | the function to call |
params | the parameters of the function |
public static Object invoke(Object object, String function, Object... params)
//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; } }