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

org.bonitasoft.engine.commons.ClassReflector Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2019 Bonitasoft S.A.
 * Bonitasoft, 32 rue Gustave Eiffel - 38000 Grenoble
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation
 * version 2.1 of the License.
 * This library 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 Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License along with this
 * program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
 * Floor, Boston, MA 02110-1301, USA.
 **/
package org.bonitasoft.engine.commons;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.text.WordUtils;
import org.bonitasoft.engine.commons.exceptions.SReflectException;

/**
 * @author Baptiste Mesta
 * @author Matthieu Chaffotte
 * @author Laurent Leseigneur
 */
public class ClassReflector {

    private static final String EMPTY = "";

    private static final String SET = "set";

    private static final String IS = "is";

    private static final String GET = "get";

    private static final Map methods;

    static {
        methods = new HashMap<>();
    }

    private static final Object MUTEX = new Object();

    public static Collection getAccessibleGetters(final Class clazz) {
        final Collection methods = new HashSet<>();
        for (final Method method : clazz.getMethods()) {
            if (isAGetterMethod(method)) {
                methods.add(method);
            }
        }
        return methods;
    }

    public static  Class getClass(final Class clazz, final String className) throws SReflectException {
        try {
            return (Class) Class.forName(className);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static  T getObject(final Class clazz, final String className) throws SReflectException {
        try {
            return getClass(clazz, className).newInstance();
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static  Constructor getConstructor(final Class clazz, final Class... parameterTypes)
            throws SReflectException {
        try {
            return clazz.getConstructor(parameterTypes);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static  Constructor getConstructor(final Class clazz, final String className,
            final Class... parameterTypes) throws SReflectException {
        try {
            return getClass(clazz, className).getConstructor(parameterTypes);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static  T getInstance(final Constructor constructor, final Object... parameters)
            throws SReflectException {
        try {
            return constructor.newInstance(parameters);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public static  T invokeGetter(final Object entity, final String getterName) throws SReflectException {
        try {
            final Method getter = getMethod(entity.getClass(), getterName);
            return (T) getter.invoke(entity, (Object[]) null);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static void invokeSetter(final Object entity, final String setterName, final Class parameterType,
            final Object parameterValue)
            throws SReflectException {
        try {
            final Method setter = getMethod(entity.getClass(), setterName, parameterType);
            setter.invoke(entity, parameterValue);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes)
            throws NoSuchMethodException {
        final StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(clazz.hashCode());
        stringBuilder.append(':');
        stringBuilder.append(clazz.getName());
        stringBuilder.append('.');
        stringBuilder.append(methodName);
        stringBuilder.append('(');
        if (parameterTypes != null) {
            for (final Class class1 : parameterTypes) {
                stringBuilder.append(class1.getName());
                stringBuilder.append(',');
            }
        }
        stringBuilder.append(')');
        final String key = stringBuilder.toString();
        putIfAbsent(clazz, methodName, key, parameterTypes);
        return methods.get(key);
    }

    private static void putIfAbsent(final Class clazz, final String methodName, final String key,
            final Class... parameterTypes)
            throws NoSuchMethodException {
        if (!methods.containsKey(key)) {
            synchronized (MUTEX) {
                // ensure that key was not put before between check and lock
                if (!methods.containsKey(key)) {
                    methods.put(key, clazz.getMethod(methodName, parameterTypes));
                }
            }
        }
    }

    public static Method getMethodByName(final Class clazz, final String methodName) {
        final String key = clazz.getName() + '.' + methodName;
        putIfAbsent(clazz, methodName, key);
        return methods.get(key);
    }

    private static void putIfAbsent(final Class clazz, final String methodName, final String key) {
        if (!methods.containsKey(key)) {
            synchronized (MUTEX) {
                // ensure that key was not put before between check and lock
                if (!methods.containsKey(key)) {
                    final Method method = getFirstMethodWithName(clazz, methodName);
                    methods.put(key, method);
                }
            }
        }
    }

    public static Method getFirstMethodWithName(final Class clazz, final String methodName) {
        Method selectedMethod = null;
        for (final Method method : clazz.getMethods()) {
            if (method.getName().equals(methodName)) {
                selectedMethod = method;
                break;
            }
        }
        return selectedMethod;
    }

    public static Object invokeMethodByName(final Object entity, final String methodName,
            final Object... parameterValues) throws SReflectException {
        final Class clazz = entity.getClass();
        // no check on parameters
        final Method methodToInvoke = getMethodByName(clazz, methodName);
        if (methodToInvoke == null) {
            throw new SReflectException(
                    "unable to find a method with name '" + methodName + "' within class " + clazz.getName());
        }
        try {
            return methodToInvoke.invoke(entity, parameterValues);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
    }

    public static Object invokeMethod(final Object entity, final String methodName, final Class parameterType,
            final Object parameterValue)
            throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        final Method method = getMethod(entity.getClass(), methodName, parameterType);
        return method.invoke(entity, parameterValue);
    }

    public static Object invokeMethod(final Object entity, final String methodName, final Class[] parameterType,
            final Object[] parameterValue)
            throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        final Method method = getMethod(entity.getClass(), methodName, parameterType);
        return method.invoke(entity, parameterValue);
    }

    private static boolean isWrapped(final Class a, final Class b) {
        return a.equals(int.class) && b.equals(Integer.class) || a.equals(double.class) && b.equals(Double.class)
                || a.equals(boolean.class)
                        && b.equals(Boolean.class)
                || a.equals(char.class) && b.equals(Character.class) || a.equals(long.class) && b.equals(Long.class)
                || a.equals(short.class) && b.equals(Short.class) || a.equals(float.class) && b.equals(Float.class)
                || a.equals(byte.class)
                        && b.equals(Byte.class);
    }

    public static Method getCompatibleMethod(final Class clazz, final String methodName,
            final Class... paramTypes) throws SReflectException {
        try {
            return clazz.getMethod(methodName, paramTypes);
        } catch (final Exception e) {
            if (paramTypes != null) {
                final Method[] methods = clazz.getMethods();
                for (final Method method : methods) {
                    if (methodName.equals(method.getName())) {
                        final Class[] types = method.getParameterTypes();
                        boolean check = true;
                        if (!(types.length == paramTypes.length)) {
                            throw new SReflectException("wrong parameters");
                        }
                        for (int i = 0; i < types.length; i++) {
                            if (!(types[i].isAssignableFrom(paramTypes[i]) || paramTypes[i].isAssignableFrom(types[i])
                                    || isWrapped(types[i], paramTypes[i]))) {
                                check = false;
                                break;
                            }
                        }
                        if (check) {
                            return method;
                        }
                    }
                }
            }
            throw new SReflectException(e);
        }
    }

    public static Type getGetterReturnType(final Class classConnector, final String getterName)
            throws SReflectException {
        Method m;
        try {
            m = getMethod(classConnector, getterName);
        } catch (final Exception e) {
            throw new SReflectException(e);
        }
        return m.getGenericReturnType();
    }

    public static Method[] getDeclaredSetters(final Class clazz) {
        final List setters = new ArrayList<>();
        final Method[] methods = clazz.getDeclaredMethods();
        for (final Method method : methods) {
            if (isASetterMethod(method)) {
                setters.add(method);
            }
        }
        return setters.toArray(new Method[setters.size()]);
    }

    public static Method[] getDeclaredGetters(final Class clazz) {
        final List getters = new ArrayList<>();
        final Method[] methods = clazz.getDeclaredMethods();
        for (final Method method : methods) {
            if (isAGetterMethod(method)) {
                getters.add(method);
            }
        }
        return getters.toArray(new Method[getters.size()]);
    }

    public static boolean isAGetterMethod(final Method method) {
        final String methodName = method.getName();
        return (methodName.startsWith(GET) || methodName.startsWith(IS)) && method.getParameterTypes().length == 0
                && !Void.class.equals(method.getReturnType());
    }

    public static boolean isASetterMethod(final Method method) {
        final String methodName = method.getName();
        return methodName.startsWith(SET) && "void".equals(method.getReturnType().toString())
                && method.getParameterTypes().length == 1;
    }

    public static String getGetterName(final String fieldName) {
        return "get" + WordUtils.capitalize(fieldName);
    }

    public static String getGetterName(final String fieldName, final Class fieldType) {
        return getGetterPrefix(fieldType) + WordUtils.capitalize(fieldName);
    }

    private static String getGetterPrefix(Class fieldType) {
        if (fieldType.isAssignableFrom(Boolean.class)) {
            return IS;
        }
        return GET;

    }

    public static String getFieldName(final String methodName) {
        int cut = 4;
        if (methodName.startsWith(IS)) {
            cut = 3;
        }
        if (methodName.length() < cut) {
            return EMPTY;
        }
        final String end = methodName.substring(cut);
        final char c = methodName.charAt(cut - 1);
        final String begin = String.valueOf(c).toLowerCase();
        return begin.concat(end);
    }

    /**
     * call a setter by reflection
     * support pointed notation like pojo.child.name
     *
     * @param object
     *        object on with to call the setter
     * @param fieldName
     * @param parameterValue
     * @throws SReflectException
     */
    public static void setField(Object object, String fieldName, Object parameterValue) throws SReflectException {
        String[] getters = fieldName.split("\\.");
        int i;
        for (i = 0; i < getters.length - 1; i++) {
            object = invokeMethodByName(object, getGetterName(getters[i]));
        }

        invokeMethodByName(object, getSetterName(getters[i]), parameterValue);

    }

    private static String getSetterName(String getter) {
        return "set" + WordUtils.capitalize(getter);
    }

    public static void clearCache() {
        methods.clear();
    }

    public static int getCacheSize() {
        return methods.size();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy