1 package com.atlassian.plugin.util;
2
3 import java.lang.reflect.Array;
4 import java.lang.reflect.GenericArrayType;
5 import java.lang.reflect.ParameterizedType;
6 import java.lang.reflect.Type;
7 import java.lang.reflect.TypeVariable;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14
15
16
17
18 public class ClassUtils {
19 private ClassUtils() {
20 }
21
22
23
24
25
26
27
28 public static Set<Class> findAllTypes(Class cls) {
29 Set<Class> types = new HashSet<>();
30 findAllTypes(cls, types);
31 return types;
32 }
33
34
35
36
37
38
39
40 public static void findAllTypes(Class cls, Set<Class> types) {
41 if (cls == null) {
42 return;
43 }
44
45
46 if (types.contains(cls)) {
47 return;
48 }
49
50 types.add(cls);
51
52 findAllTypes(cls.getSuperclass(), types);
53 for (int x = 0; x < cls.getInterfaces().length; x++) {
54 findAllTypes(cls.getInterfaces()[x], types);
55 }
56 }
57
58
59
60
61
62
63
64 private static Class<?> getClass(Type type) {
65 if (type instanceof Class) {
66 return (Class) type;
67 } else if (type instanceof ParameterizedType) {
68 return getClass(((ParameterizedType) type).getRawType());
69 } else if (type instanceof GenericArrayType) {
70 Type componentType = ((GenericArrayType) type).getGenericComponentType();
71 Class<?> componentClass = getClass(componentType);
72 if (componentClass != null) {
73 return Array.newInstance(componentClass, 0).getClass();
74 } else {
75 return null;
76 }
77 } else {
78 return null;
79 }
80 }
81
82
83
84
85
86
87
88
89
90
91 public static <T> List<Class<?>> getTypeArguments(
92 Class<T> baseClass, Class<? extends T> childClass) {
93 Map<Type, Type> resolvedTypes = new HashMap<>();
94 Type type = childClass;
95 Class typeClass = getClass(type);
96
97 while (!typeClass.equals(baseClass)) {
98 if (type instanceof Class) {
99
100 type = ((Class) type).getGenericSuperclass();
101 } else {
102 ParameterizedType parameterizedType = (ParameterizedType) type;
103 Class<?> rawType = (Class) parameterizedType.getRawType();
104
105 Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
106 TypeVariable<?>[] typeParameters = rawType.getTypeParameters();
107 for (int i = 0; i < actualTypeArguments.length; i++) {
108 resolvedTypes.put(typeParameters[i], actualTypeArguments[i]);
109 }
110
111 if (!rawType.equals(baseClass)) {
112 type = rawType.getGenericSuperclass();
113 }
114 }
115 typeClass = getClass(type);
116 if (typeClass == null) {
117 throw new IllegalArgumentException("Unable to find the class for the type " + type);
118 }
119 }
120
121
122
123 Type[] actualTypeArguments;
124 if (type instanceof Class) {
125 actualTypeArguments = ((Class) type).getTypeParameters();
126 } else {
127 actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
128 }
129 List<Class<?>> typeArgumentsAsClasses = new ArrayList<>();
130
131 for (Type baseType : actualTypeArguments) {
132 while (resolvedTypes.containsKey(baseType)) {
133 baseType = resolvedTypes.get(baseType);
134 }
135 typeArgumentsAsClasses.add(getClass(baseType));
136 }
137 return typeArgumentsAsClasses;
138 }
139 }