1
+ package hello .util ;
2
+
3
+ import java .lang .reflect .Field ;
4
+ import java .lang .reflect .InvocationTargetException ;
5
+ import java .lang .reflect .Method ;
6
+ import java .util .ArrayList ;
7
+ import java .util .Arrays ;
8
+ import java .util .List ;
9
+ import java .util .Optional ;
10
+ import java .util .stream .Stream ;
11
+
12
+ public final class ReflectionUtils {
13
+
14
+ private ReflectionUtils () { }
15
+
16
+ private static final String GETTER_PREFIX = "get" ;
17
+ private static final String SETTER_PREFIX = "set" ;
18
+
19
+ /**
20
+ * Get name of getter
21
+ *
22
+ * @param fieldName fieldName
23
+ * @return getter name
24
+ */
25
+ public static String getterByFieldName (String fieldName ) {
26
+ if (isStringNullOrEmpty (fieldName ))
27
+ return null ;
28
+
29
+ return convertFieldByAddingPrefix (fieldName , GETTER_PREFIX );
30
+ }
31
+
32
+ /**
33
+ * Get name of setter
34
+ *
35
+ * @param fieldName fieldName
36
+ * @return setter name
37
+ */
38
+ public static String setterByFieldName (String fieldName ) {
39
+ if (isStringNullOrEmpty (fieldName ))
40
+ return null ;
41
+
42
+ return convertFieldByAddingPrefix (fieldName , SETTER_PREFIX );
43
+ }
44
+
45
+ /**
46
+ * Get the contents of the field with any access modifier
47
+ *
48
+ * @param obj obj
49
+ * @param fieldName fieldName
50
+ * @return content of field
51
+ */
52
+ public static Object getFieldContent (Object obj , String fieldName ) {
53
+ if (!isValidParams (obj , fieldName ))
54
+ return null ;
55
+
56
+ try {
57
+ Field declaredField = getFieldAccessible (obj , fieldName );
58
+ return declaredField .get (obj );
59
+ } catch (IllegalAccessException e ) {
60
+ throw new IllegalArgumentException ("Cannot get field content for field name: " + fieldName , e );
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Set the contents to the field with any access modifier
66
+ *
67
+ * @param obj obj
68
+ * @param fieldName fieldName
69
+ * @param value value
70
+ */
71
+ public static void setFieldContent (Object obj , String fieldName , Object value ) {
72
+ if (!isValidParams (obj , fieldName ))
73
+ return ;
74
+
75
+ try {
76
+ Field declaredField = getFieldAccessible (obj , fieldName );
77
+ declaredField .set (obj , value );
78
+ } catch (IllegalAccessException e ) {
79
+ throw new IllegalArgumentException ("Cannot set field content for field name: " + fieldName , e );
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Call a method with any access modifier
85
+ *
86
+ * @param obj obj
87
+ * @param methodName methodName
88
+ * @return result of method
89
+ */
90
+ public static Object callMethod (Object obj , String methodName ) {
91
+ if (!isValidParams (obj , methodName ))
92
+ return null ;
93
+
94
+ try {
95
+ Method method = obj .getClass ().getMethod (methodName );
96
+ method .setAccessible (true );
97
+ return method .invoke (obj );
98
+ } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e ) {
99
+ throw new IllegalArgumentException ("Cannot invoke method name: " + methodName , e );
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Get all fields even from parent
105
+ *
106
+ * @param clazz clazz
107
+ * @return array of fields
108
+ */
109
+ public static Field [] getAllFields (Class <?> clazz ) {
110
+ if (clazz == null ) return null ;
111
+
112
+ List <Field > fields = new ArrayList <>(Arrays .asList (clazz .getDeclaredFields ()));
113
+ if (clazz .getSuperclass () != null ) {
114
+ // danger! Recursion
115
+ fields .addAll (Arrays .asList (getAllFields (clazz .getSuperclass ())));
116
+ }
117
+ return fields .toArray (new Field [] {});
118
+ }
119
+
120
+ /**
121
+ * Get the Field from Object even from parent
122
+ *
123
+ * @param obj obj
124
+ * @param fieldName fieldName
125
+ * @return {@code Optional}
126
+ */
127
+ public static Optional <Field > getField (Object obj , String fieldName ) {
128
+ if (!isValidParams (obj , fieldName ))
129
+ return Optional .empty ();
130
+
131
+ Class <?> clazz = obj .getClass ();
132
+ return getField (clazz , fieldName );
133
+ }
134
+
135
+ /**
136
+ * Get the Field from Class even from parent
137
+ *
138
+ * @param clazz clazz
139
+ * @param fieldName fieldName
140
+ * @return {@code Optional}
141
+ */
142
+ public static Optional <Field > getField (Class <?> clazz , String fieldName ) {
143
+ if (!isValidParams (clazz , fieldName ))
144
+ return Optional .empty ();
145
+
146
+ Field [] fields = getAllFields (clazz );
147
+ return Stream .of (fields )
148
+ .filter (x -> x .getName ().equals (fieldName ))
149
+ .findFirst ();
150
+ }
151
+
152
+ /**
153
+ * @param clazz clazz
154
+ * @param fieldName fieldName
155
+ * @return Class
156
+ */
157
+ public static Class <?> getFieldType (Class <?> clazz , String fieldName ) {
158
+ return getFieldWithCheck (clazz , fieldName ).getType ();
159
+ }
160
+
161
+ /**
162
+ * @param clazz clazz
163
+ * @param fieldName fieldName
164
+ * @return Field
165
+ */
166
+ public static Field getFieldWithCheck (Class <?> clazz , String fieldName ) {
167
+ return ReflectionUtils .getField (clazz , fieldName )
168
+ .orElseThrow (() -> {
169
+ String msg = String .format ("Cannot find field name: '%s' from class: '%s'" , fieldName , clazz );
170
+ return new IllegalArgumentException (msg );
171
+ });
172
+ }
173
+
174
+ /**
175
+ * Get the field values with the types already listed according to the field type
176
+ *
177
+ * @param clazz clazz
178
+ * @param fieldName fieldName
179
+ * @param fieldValue fieldValue
180
+ * @return value cast to specific field type
181
+ */
182
+ public static Object castFieldValueByClass (Class <?> clazz , String fieldName , Object fieldValue ) {
183
+ Field field = getField (clazz , fieldName )
184
+ .orElseThrow (() -> new IllegalArgumentException (String .format ("Cannot find field by name: '%s'" , fieldName )));
185
+
186
+ Class <?> fieldType = field .getType ();
187
+
188
+ return castFieldValueByType (fieldType , fieldValue );
189
+ }
190
+
191
+ /**
192
+ * @param fieldType fieldType
193
+ * @param fieldValue fieldValue
194
+ * @return casted value
195
+ */
196
+ public static Object castFieldValueByType (Class <?> fieldType , Object fieldValue ) {
197
+ if (fieldType .isAssignableFrom (Boolean .class )) {
198
+ if (fieldValue instanceof String ) {
199
+ return convertStringToBoolean ((String ) fieldValue );
200
+ }
201
+ if (fieldValue instanceof Number ) {
202
+ return !(fieldValue ).equals (0 );
203
+ }
204
+ return fieldValue ;
205
+ }
206
+
207
+ else if (fieldType .isAssignableFrom (Double .class )) {
208
+ if (fieldValue instanceof String ) {
209
+ return Double .valueOf ((String )fieldValue );
210
+ }
211
+ return ((Number ) fieldValue ).doubleValue ();
212
+ }
213
+
214
+ else if (fieldType .isAssignableFrom (Long .class )) {
215
+ if (fieldValue instanceof String ) {
216
+ return Long .valueOf ((String )fieldValue );
217
+ }
218
+ return ((Number ) fieldValue ).longValue ();
219
+ }
220
+
221
+ else if (fieldType .isAssignableFrom (Float .class )) {
222
+ if (fieldValue instanceof String ) {
223
+ return Float .valueOf ((String )fieldValue );
224
+ }
225
+ return ((Number ) fieldValue ).floatValue ();
226
+ }
227
+
228
+ else if (fieldType .isAssignableFrom (Integer .class )) {
229
+ if (fieldValue instanceof String ) {
230
+ return Integer .valueOf ((String )fieldValue );
231
+ }
232
+ return ((Number ) fieldValue ).intValue ();
233
+ }
234
+
235
+ else if (fieldType .isAssignableFrom (Short .class )) {
236
+ if (fieldValue instanceof String ) {
237
+ return Short .valueOf ((String )fieldValue );
238
+ }
239
+ return ((Number ) fieldValue ).shortValue ();
240
+ }
241
+
242
+ return fieldValue ;
243
+ }
244
+
245
+ private static boolean convertStringToBoolean (String s ) {
246
+ String trim = s .trim ();
247
+ return !trim .equals ("" ) && !trim .equals ("0" ) && !trim .toLowerCase ().equals ("false" );
248
+ }
249
+
250
+ private static boolean isValidParams (Object obj , String param ) {
251
+ return (obj != null && !isStringNullOrEmpty (param ));
252
+ }
253
+
254
+ private static boolean isStringNullOrEmpty (String fieldName ) {
255
+ return fieldName == null || fieldName .trim ().length () == 0 ;
256
+ }
257
+
258
+ private static Field getFieldAccessible (Object obj , String fieldName ) {
259
+ Optional <Field > optionalField = getField (obj , fieldName );
260
+ return optionalField
261
+ .map (el -> {
262
+ el .setAccessible (true );
263
+ return el ;
264
+ })
265
+ .orElseThrow (() -> new IllegalArgumentException ("Cannot find field name: " + fieldName ));
266
+ }
267
+
268
+ private static String convertFieldByAddingPrefix (String fieldName , String prefix ) {
269
+ return prefix + fieldName .substring (0 , 1 ).toUpperCase () + fieldName .substring (1 );
270
+ }
271
+ }
0 commit comments