]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/common/ReflectionHelper.java
a350d459ba9814dcecd6ea43a369cbaf5f42ae03
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / common / ReflectionHelper.java
1 package com.irtimaled.bbor.common;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Field;
5 import java.lang.reflect.ParameterizedType;
6 import java.lang.reflect.Type;
7 import java.util.function.Function;
8
9 public class ReflectionHelper {
10     public static <T, R> Function<T, R> getPrivateFieldGetter(Class<?> clazz, Type fieldType, Type... genericTypeArguments) {
11         Field field = findField(clazz, fieldType, genericTypeArguments);
12         if (field == null) return obj -> null;
13
14         field.setAccessible(true);
15         return obj -> {
16             try {
17                 return (R) field.get(obj);
18             } catch (IllegalAccessException ignored) {
19                 return null;
20             }
21         };
22     }
23
24     private static Field findField(Class<?> clazz, Type fieldType, Type[] genericTypeArguments) {
25         for (Field field : clazz.getDeclaredFields()) {
26             Type type = field.getGenericType();
27             ParameterizedType genericType = TypeHelper.as(type, ParameterizedType.class);
28             if (genericType == null) {
29                 if (type != fieldType || genericTypeArguments.length > 0) continue;
30                 return field;
31             }
32
33             Type rawType = genericType.getRawType();
34             if (rawType != fieldType) continue;
35
36             Type[] actualTypeArguments = genericType.getActualTypeArguments();
37             if (!typesMatch(genericTypeArguments, actualTypeArguments)) continue;
38
39             return field;
40         }
41         return null;
42     }
43
44     private static boolean typesMatch(Type[] left, Type[] right) {
45         if (left.length != right.length) return false;
46
47         for (int index = 0; index < right.length; index++) {
48             if (right[index] != left[index]) {
49                 return false;
50             }
51         }
52         return true;
53     }
54
55     public static <T, R> Function<T, R> getPrivateInstanceBuilder(Class<R> clazz, Class<T> parameter) {
56         Constructor<R> constructor = findConstructor(clazz, parameter);
57         if (constructor == null) return obj -> null;
58
59         constructor.setAccessible(true);
60         return obj -> {
61             try {
62                 return (R) constructor.newInstance(obj);
63             } catch (Exception ignored) {
64                 return null;
65             }
66         };
67     }
68
69     private static <T> Constructor<T> findConstructor(Class<T> clazz, Class<?>... parameters) {
70         try {
71             return clazz.getDeclaredConstructor(parameters);
72         } catch (NoSuchMethodException ignored) {
73             return null;
74         }
75     }
76 }