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

org.junit.contrib.theories.ParameterSignature Maven / Gradle / Ivy

package org.junit.contrib.theories;

import org.javaruntype.type.Types;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Executable;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ParameterSignature implements AnnotatedElement {
    private static final Map CONVERTIBLE_TYPES_MAP = buildConvertibleTypesMap();

    private static Map buildConvertibleTypesMap() {
        Map, Class> map = new HashMap<>();

        putSymmetrically(map, boolean.class, Boolean.class);
        putSymmetrically(map, byte.class, Byte.class);
        putSymmetrically(map, short.class, Short.class);
        putSymmetrically(map, char.class, Character.class);
        putSymmetrically(map, int.class, Integer.class);
        putSymmetrically(map, long.class, Long.class);
        putSymmetrically(map, float.class, Float.class);
        putSymmetrically(map, double.class, Double.class);

        return Collections.unmodifiableMap(map);
    }

    private static  void putSymmetrically(Map map, T a, T b) {
        map.put(a, b);
        map.put(b, a);
    }

    public static List signatures(Executable e) {
        List sigs = new ArrayList<>();
        for (Parameter each : e.getParameters()) {
            sigs.add(new ParameterSignature(each));
        }
        return sigs;
    }

    private final Parameter parameter;

    private ParameterSignature(Parameter parameter) {
        this.parameter = parameter;
    }

    public boolean canAcceptValue(Object candidate) {
        return candidate == null
                ? !Types.forJavaLangReflectType(getType()).getRawClass().isPrimitive()
                : canAcceptType(candidate.getClass());
    }

    public boolean canAcceptType(Type candidate) {
        return assignable(getType(), candidate) || isAssignableViaTypeConversion(getType(), candidate);
    }

    public boolean canPotentiallyAcceptType(Class candidate) {
        return assignable(candidate, getType())
                || isAssignableViaTypeConversion(candidate, getType())
                || canAcceptType(candidate);
    }

    private static boolean isAssignableViaTypeConversion(Type targetType, Type candidate) {
        if (CONVERTIBLE_TYPES_MAP.containsKey(candidate)) {
            Type wrapper = CONVERTIBLE_TYPES_MAP.get(candidate);
            return assignable(targetType, wrapper);
        }
        return false;
    }

    private static boolean assignable(Type first, Type second) {
        return Types.forJavaLangReflectType(first).isAssignableFrom(Types.forJavaLangReflectType(second));
    }

    public Type getType() {
        return getAnnotatedType().getType();
    }

    public AnnotatedType getAnnotatedType() {
        return parameter.getAnnotatedType();
    }

    @Override
    public Annotation[] getAnnotations() {
        return parameter.getAnnotations();
    }

    @Override
    public Annotation[] getDeclaredAnnotations() {
        return parameter.getDeclaredAnnotations();
    }

    public String getName() {
        return parameter.getName();
    }

    public String getDeclarerName() {
        Executable exec = parameter.getDeclaringExecutable();
        return exec.getDeclaringClass().getName() + '.' + exec.getName();
    }

    public boolean hasAnnotation(Class type) {
        return getAnnotation(type) != null;
    }

    public  T findDeepAnnotation(Class annotationType) {
        return findDeepAnnotation(parameter.getAnnotations(), annotationType, 3);
    }

    private  T findDeepAnnotation(Annotation[] annotations,
            Class annotationType, int depth) {

        if (depth == 0) {
            return null;
        }

        for (Annotation each : annotations) {
            if (annotationType.isInstance(each)) {
                return annotationType.cast(each);
            }

            Annotation candidate =
                    findDeepAnnotation(each.annotationType().getAnnotations(), annotationType, depth - 1);
            if (candidate != null) {
                return annotationType.cast(candidate);
            }
        }

        return null;
    }

    public  T getAnnotation(Class annotationType) {
        for (Annotation each : getAnnotations()) {
            if (annotationType.isInstance(each)) {
                return annotationType.cast(each);
            }
        }

        return null;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy