1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.reflection;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 import java.lang.reflect.ParameterizedType;
21 import java.lang.reflect.Type;
22 import java.util.Collection;
23
24 import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
25 import org.apache.ibatis.reflection.invoker.Invoker;
26 import org.apache.ibatis.reflection.invoker.MethodInvoker;
27 import org.apache.ibatis.reflection.property.PropertyTokenizer;
28
29
30
31
32 public class MetaClass {
33
34 private final ReflectorFactory reflectorFactory;
35 private final Reflector reflector;
36
37 private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
38 this.reflectorFactory = reflectorFactory;
39 this.reflector = reflectorFactory.findForClass(type);
40 }
41
42 public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
43 return new MetaClass(type, reflectorFactory);
44 }
45
46 public MetaClass metaClassForProperty(String name) {
47 Class<?> propType = reflector.getGetterType(name);
48 return MetaClass.forClass(propType, reflectorFactory);
49 }
50
51 public String findProperty(String name) {
52 StringBuilder prop = buildProperty(name, new StringBuilder());
53 return prop.length() > 0 ? prop.toString() : null;
54 }
55
56 public String findProperty(String name, boolean useCamelCaseMapping) {
57 if (useCamelCaseMapping) {
58 name = name.replace("_", "");
59 }
60 return findProperty(name);
61 }
62
63 public String[] getGetterNames() {
64 return reflector.getGetablePropertyNames();
65 }
66
67 public String[] getSetterNames() {
68 return reflector.getSetablePropertyNames();
69 }
70
71 public Class<?> getSetterType(String name) {
72 PropertyTokenizer prop = new PropertyTokenizer(name);
73 if (prop.hasNext()) {
74 MetaClass metaProp = metaClassForProperty(prop.getName());
75 return metaProp.getSetterType(prop.getChildren());
76 } else {
77 return reflector.getSetterType(prop.getName());
78 }
79 }
80
81 public Class<?> getGetterType(String name) {
82 PropertyTokenizer prop = new PropertyTokenizer(name);
83 if (prop.hasNext()) {
84 MetaClass metaProp = metaClassForProperty(prop);
85 return metaProp.getGetterType(prop.getChildren());
86 }
87
88 return getGetterType(prop);
89 }
90
91 private MetaClass metaClassForProperty(PropertyTokenizer prop) {
92 Class<?> propType = getGetterType(prop);
93 return MetaClass.forClass(propType, reflectorFactory);
94 }
95
96 private Class<?> getGetterType(PropertyTokenizer prop) {
97 Class<?> type = reflector.getGetterType(prop.getName());
98 if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
99 Type returnType = getGenericGetterType(prop.getName());
100 if (returnType instanceof ParameterizedType) {
101 Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
102 if (actualTypeArguments != null && actualTypeArguments.length == 1) {
103 returnType = actualTypeArguments[0];
104 if (returnType instanceof Class) {
105 type = (Class<?>) returnType;
106 } else if (returnType instanceof ParameterizedType) {
107 type = (Class<?>) ((ParameterizedType) returnType).getRawType();
108 }
109 }
110 }
111 }
112 return type;
113 }
114
115 private Type getGenericGetterType(String propertyName) {
116 try {
117 Invoker invoker = reflector.getGetInvoker(propertyName);
118 if (invoker instanceof MethodInvoker) {
119 Field declaredMethod = MethodInvoker.class.getDeclaredField("method");
120 declaredMethod.setAccessible(true);
121 Method method = (Method) declaredMethod.get(invoker);
122 return TypeParameterResolver.resolveReturnType(method, reflector.getType());
123 } else if (invoker instanceof GetFieldInvoker) {
124 Field declaredField = GetFieldInvoker.class.getDeclaredField("field");
125 declaredField.setAccessible(true);
126 Field field = (Field) declaredField.get(invoker);
127 return TypeParameterResolver.resolveFieldType(field, reflector.getType());
128 }
129 } catch (NoSuchFieldException | IllegalAccessException e) {
130
131 }
132 return null;
133 }
134
135 public boolean hasSetter(String name) {
136 PropertyTokenizer prop = new PropertyTokenizer(name);
137 if (prop.hasNext()) {
138 if (reflector.hasSetter(prop.getName())) {
139 MetaClass metaProp = metaClassForProperty(prop.getName());
140 return metaProp.hasSetter(prop.getChildren());
141 } else {
142 return false;
143 }
144 } else {
145 return reflector.hasSetter(prop.getName());
146 }
147 }
148
149 public boolean hasGetter(String name) {
150 PropertyTokenizer prop = new PropertyTokenizer(name);
151 if (prop.hasNext()) {
152 if (reflector.hasGetter(prop.getName())) {
153 MetaClass metaProp = metaClassForProperty(prop);
154 return metaProp.hasGetter(prop.getChildren());
155 } else {
156 return false;
157 }
158 } else {
159 return reflector.hasGetter(prop.getName());
160 }
161 }
162
163 public Invoker getGetInvoker(String name) {
164 return reflector.getGetInvoker(name);
165 }
166
167 public Invoker getSetInvoker(String name) {
168 return reflector.getSetInvoker(name);
169 }
170
171 private StringBuilder buildProperty(String name, StringBuilder builder) {
172 PropertyTokenizer prop = new PropertyTokenizer(name);
173 if (prop.hasNext()) {
174 String propertyName = reflector.findPropertyName(prop.getName());
175 if (propertyName != null) {
176 builder.append(propertyName);
177 builder.append(".");
178 MetaClass metaProp = metaClassForProperty(propertyName);
179 metaProp.buildProperty(prop.getChildren(), builder);
180 }
181 } else {
182 String propertyName = reflector.findPropertyName(name);
183 if (propertyName != null) {
184 builder.append(propertyName);
185 }
186 }
187 return builder;
188 }
189
190 public boolean hasDefaultConstructor() {
191 return reflector.hasDefaultConstructor();
192 }
193
194 }