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

org.simpleflatmapper.reflect.ReflectionInstantiatorDefinitionFactory Maven / Gradle / Ivy

package org.simpleflatmapper.reflect;

import org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition;
import org.simpleflatmapper.util.TypeHelper;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class ReflectionInstantiatorDefinitionFactory {

    interface ParameterBuilder {
        Parameter[] getParameters(Method m, Type target);
        Parameter[] getParameters(Constructor c, Type target);
    }

    public static List extractDefinitions(Type target) {
        if (areParameterNamePresent(target)) {
            return extractDefinitionsWithParamNames(target);
        } else {
            return extractDefinitionsWithoutParamNames(target);
        }
    }

    public static InstantiatorDefinition definition(Method m) {
        //IFJAVA8_START
        if (m.getParameters().length > 0 && m.getParameters()[0].isNamePresent()) {
            Parameter[] parameters = new Parameter[m.getParameters().length];
            final java.lang.reflect.Parameter[] ps = m.getParameters();


            for (int i = 0; i < parameters.length; i++) {
                parameters[i] = new Parameter(i, ps[i].getName(), ps[i].getType(), ps[i].getParameterizedType());
            }
            return new ExecutableInstantiatorDefinition(m , parameters);
        }
        //IFJAVA8_END
        final Parameter[] parameters = ReflectionInstantiatorDefinitionFactory.getParameters(m, m.getGenericReturnType());
        return new ExecutableInstantiatorDefinition(m, parameters);
    }



    @SuppressWarnings("unchecked")
    private static List extractDefinitionsWithoutParamNames(Type target) {
        return extractDefinitions(target, new ParameterBuilder() {

            @Override
            public Parameter[] getParameters(Method m, Type target) {
                return ReflectionInstantiatorDefinitionFactory.getParameters(m, target);
            }

            @Override
            public Parameter[] getParameters(Constructor c, Type target) {
                return ReflectionInstantiatorDefinitionFactory.getParameters(c, target);
            }
        });
    }
    @SuppressWarnings("unchecked")
    private static List extractDefinitionsWithParamNames(Type target) {
        return extractDefinitions(target, new ParameterBuilder() {
            @Override
            public Parameter[] getParameters(Method m, Type target) {
                //IFJAVA8_START
                if (true) {
                    return getParametersWithName(m);
                }
                //IFJAVA8_END
                throw new IllegalStateException("Only supported on java8");
            }

            @Override
            public Parameter[] getParameters(Constructor c, Type target) {
                //IFJAVA8_START
                if (true) {
                    return getParametersWithName(c);
                }
                //IFJAVA8_END
                throw new IllegalStateException("Only supported on java8");
            }
        });
    }

    @SuppressWarnings("unchecked")
    private static List extractDefinitions(Type target, ParameterBuilder parameterBuilder) {
        Class clazz = TypeHelper.toClass(target);
        List instantiatorDefinitions = new ArrayList();

        for(Constructor constructor : clazz.getDeclaredConstructors()) {
            if (Modifier.isPublic(constructor.getModifiers())) {
                InstantiatorDefinition definition = new ExecutableInstantiatorDefinition(constructor, parameterBuilder.getParameters(constructor, target));
                instantiatorDefinitions.add(definition);
            }
        }

        for(Method m : clazz.getDeclaredMethods()) {
            if (Modifier.isPublic(m.getModifiers())
                    && Modifier.isStatic(m.getModifiers())
                    && clazz.isAssignableFrom(m.getReturnType())) {
                InstantiatorDefinition definition = new ExecutableInstantiatorDefinition(m, parameterBuilder.getParameters(m, target));
                instantiatorDefinitions.add(definition);
            }
        }

        return instantiatorDefinitions;
    }

    //IFJAVA8_START
    private static Parameter[] getParametersWithName(Executable m) {

        final java.lang.reflect.Parameter[] ps = m.getParameters();
        Parameter[] parameters = new Parameter[ps.length];

        for(int i = 0; i < parameters.length; i++) {
            parameters[i] = new Parameter(i, ps[i].getName(), ps[i].getType(), ps[i].getParameterizedType());
        }

        return  parameters;
    }
    //IFJAVA8_END

    private static Parameter[] getParameters(Constructor constructor, Type target) {
        return buildParameters(target, constructor.getParameterTypes(), constructor.getGenericParameterTypes(), TypeHelper.toClass(target).getTypeParameters());
    }


    private static Parameter[] getParameters(Method method, Type target) {
        return buildParameters(target, method.getParameterTypes(), method.getGenericParameterTypes(), TypeHelper.toClass(target).getTypeParameters());
    }

    private static Parameter[] buildParameters(Type target, Class[] parameterTypes, Type[] parameterGenericTypes, TypeVariable>[] targetClassTypeParameters) {
        Parameter[] parameters = new Parameter[parameterTypes.length];
        for(int i = 0; i < parameters.length; i++) {
            Type paramType = parameterGenericTypes[i];
            Type resolvedParamType = null;
            if (paramType instanceof TypeVariable) {
                TypeVariable tv = (TypeVariable) paramType;
                paramType = parameterTypes[i];
                if (target instanceof ParameterizedType) {
                    ParameterizedType pt = (ParameterizedType) target;
                    int j = 0;
                    for (TypeVariable> typeParameter : targetClassTypeParameters) {
                        if (typeParameter.getName().equals(tv.getName())) {
                            Type[] actualTypeArguments = pt.getActualTypeArguments();
                            resolvedParamType = actualTypeArguments[j];
                            break;
                        }
                        j++;
                    }
                }
            }
            if (resolvedParamType == null) {
                resolvedParamType = paramType;
            }
            parameters[i] = new Parameter(i, null, TypeHelper.toClass(paramType), resolvedParamType);
        }

        return parameters;
    }

    public static boolean areParameterNamePresent(Type target) {
        //IFJAVA8_START
        if (_areParameterNamePresent(target)) {
            return true;
        }
        //IFJAVA8_END
        return false;
    }

    //IFJAVA8_START
    // assume parameter name are either present or not for the type
    private static boolean _areParameterNamePresent(Type target) {
        Class targetClass = TypeHelper.toClass(target);

        for(Method m : targetClass.getDeclaredMethods()) {
            final java.lang.reflect.Parameter[] parameters = m.getParameters();
            if (parameters.length > 0) {
                return parameters[0].isNamePresent();
            }
        }

        for(Constructor c : targetClass.getDeclaredConstructors()) {
            final java.lang.reflect.Parameter[] parameters = c.getParameters();
            if (parameters.length > 0) {
                return parameters[0].isNamePresent();
            }
        }

        return false;
    }
    //IFJAVA8_END
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy