summaryrefslogtreecommitdiff
path: root/src/main/java/au/id/zancanaro/javacheck/DataSourceHelper.java
blob: 522fd268664707f4b42737200f0c4295b2d7771d (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package au.id.zancanaro.javacheck;

import au.id.zancanaro.javacheck.annotations.DataSource;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;

public class DataSourceHelper {
    private final Class<?> classObject;
    private final Map<Type, Generator<?>> generators;

    public DataSourceHelper(Class<?> classObject) {
        this.classObject = classObject;
        this.generators = new HashMap<>();
    }

    public static Set<Type> validateGeneratorFields(Class<?> classObject, List<Throwable> errors) {
        Set<Type> result = new HashSet<>();

        for (Field field : classObject.getDeclaredFields()) {
            if (field.isAnnotationPresent(DataSource.class)) {
                boolean error = false;
                if (!Modifier.isStatic(field.getModifiers())) {
                    errors.add(new Error("@DataSource field " + field.getName() + " must be static"));
                    error = true;
                }
                if (!Modifier.isPublic(field.getModifiers())) {
                    errors.add(new Error("@DataSource field " + field.getName() + " must be public"));
                    error = true;
                }

                Type type = field.getGenericType();
                ParameterizedType parameterizedType;
                if (type instanceof ParameterizedType) {
                    parameterizedType = (ParameterizedType) type;
                    if (parameterizedType.getRawType() instanceof Class) {
                        Class<?> c = (Class) parameterizedType.getRawType();
                        if (c == Generator.class) {
                            if (!error) {
                                result.add(parameterizedType.getActualTypeArguments()[0]);
                            }
                        } else {
                            errors.add(new Error("@DataSource fields must be of type Generator<T>"));
                        }
                    } else {
                        errors.add(new Error("@DataSource fields must be of type Generator<T>"));
                    }
                } else {
                    errors.add(new Error("@DataSource fields must be of type Generator<T>"));
                }
            }
        }

        return result;
    }


    private static final Map<Type, Type> rawTypes;

    static {
        Map<Type, Type> types = new HashMap<>();
        types.put(Double.class, Double.TYPE);
        types.put(Float.class, Float.TYPE);
        types.put(Long.class, Long.TYPE);
        types.put(Integer.class, Integer.TYPE);
        types.put(Short.class, Short.TYPE);
        types.put(Byte.class, Byte.TYPE);
        types.put(Character.class, Character.TYPE);
        types.put(Boolean.class, Boolean.TYPE);
        rawTypes = Collections.unmodifiableMap(types);
    }

    public Map<Type, Generator<?>> computeGenerators() {
        if (generators.isEmpty()) {
            for (Field field : classObject.getDeclaredFields()) {
                if (!field.isAnnotationPresent(DataSource.class)) {
                    continue;
                }
                Type type = field.getGenericType();
                if (!(type instanceof ParameterizedType)) {
                    continue;
                }
                ParameterizedType parameterizedType = (ParameterizedType) type;
                if (!(parameterizedType.getRawType() instanceof Class)) {
                    continue;
                }
                Class<?> c = (Class) parameterizedType.getRawType();
                if (c != Generator.class) {
                    continue;
                }
                try {
                    Type target = parameterizedType.getActualTypeArguments()[0];
                    @SuppressWarnings("unchecked")
                    Generator<Object> generator = (Generator<Object>) field.get(null);
                    generators.put(target, generator);
                    if (rawTypes.containsKey(target)) {
                        generators.put(rawTypes.get(target), generator);
                    }
                } catch (IllegalAccessException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
        return generators;
    }
}