View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.reflect;
18  
19  import java.io.Serializable;
20  import java.lang.reflect.Field;
21  import java.lang.reflect.GenericArrayType;
22  import java.lang.reflect.Method;
23  import java.lang.reflect.ParameterizedType;
24  import java.lang.reflect.Type;
25  import java.lang.reflect.TypeVariable;
26  import java.lang.reflect.WildcardType;
27  import java.net.URI;
28  import java.util.ArrayList;
29  import java.util.Arrays;
30  import java.util.Collection;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.TreeSet;
35  
36  import org.apache.commons.lang3.reflect.testbed.Foo;
37  import org.apache.commons.lang3.reflect.testbed.GenericParent;
38  import org.apache.commons.lang3.reflect.testbed.GenericTypeHolder;
39  import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
40  import org.junit.Assert;
41  import org.junit.Test;
42  
43  /**
44   * Test TypeUtils
45   */
46  @SuppressWarnings({ "unchecked", "unused" , "rawtypes" })
47  //raw types, where used, are used purposely
48  public class TypeUtilsTest<B> {
49  
50      public interface This<K, V> {
51      }
52  
53      public class That<K, V> implements This<K, V> {
54      }
55  
56      public interface And<K, V> extends This<Number, Number> {
57      }
58  
59      public class The<K, V> extends That<Number, Number> implements And<String, String> {
60      }
61  
62      public class Other<T> implements This<String, T> {
63      }
64  
65      public class Thing<Q> extends Other<B> {
66      }
67  
68      public class Tester implements This<String, B> {
69      }
70  
71      public This<String, String> dis;
72  
73      public That<String, String> dat;
74  
75      public The<String, String> da;
76  
77      public Other<String> uhder;
78  
79      public Thing ding;
80  
81      public TypeUtilsTest<String>.Tester tester;
82  
83      public Tester tester2;
84  
85      public TypeUtilsTest<String>.That<String, String> dat2;
86  
87      public TypeUtilsTest<Number>.That<String, String> dat3;
88  
89      public Comparable<? extends Integer>[] intWildcardComparable;
90  
91      public static Comparable<String> stringComparable;
92  
93      public static Comparable<URI> uriComparable;
94  
95      public static Comparable<Integer> intComparable;
96  
97      public static Comparable<Long> longComparable;
98  
99      public static Comparable<?> wildcardComparable;
100 
101     public static URI uri;
102 
103     public static List<String>[] stringListArray;
104 
105     public void dummyMethod(final List list0, final List<Object> list1, final List<?> list2,
106             final List<? super Object> list3, final List<String> list4, final List<? extends String> list5,
107             final List<? super String> list6, final List[] list7, final List<Object>[] list8, final List<?>[] list9,
108             final List<? super Object>[] list10, final List<String>[] list11, final List<? extends String>[] list12,
109             final List<? super String>[] list13) {
110     }
111 
112     @SuppressWarnings("boxing") // deliberately used here
113     @Test
114     public void testIsAssignable() throws SecurityException, NoSuchMethodException,
115             NoSuchFieldException {
116         List list0 = null;
117         List<Object> list1 = null;
118         List<?> list2 = null;
119         List<? super Object> list3 = null;
120         List<String> list4 = null;
121         List<? extends String> list5 = null;
122         List<? super String> list6 = null;
123         List[] list7 = null;
124         List<Object>[] list8 = null;
125         List<?>[] list9 = null;
126         List<? super Object>[] list10 = null;
127         List<String>[] list11 = null;
128         List<? extends String>[] list12 = null;
129         List<? super String>[] list13;
130         final Class<?> clazz = getClass();
131         final Method method = clazz.getMethod("dummyMethod", List.class, List.class, List.class,
132                 List.class, List.class, List.class, List.class, List[].class, List[].class,
133                 List[].class, List[].class, List[].class, List[].class, List[].class);
134         final Type[] types = method.getGenericParameterTypes();
135 //        list0 = list0;
136         delegateBooleanAssertion(types, 0, 0, true);
137         list1 = list0;
138         delegateBooleanAssertion(types, 0, 1, true);
139         list0 = list1;
140         delegateBooleanAssertion(types, 1, 0, true);
141         list2 = list0;
142         delegateBooleanAssertion(types, 0, 2, true);
143         list0 = list2;
144         delegateBooleanAssertion(types, 2, 0, true);
145         list3 = list0;
146         delegateBooleanAssertion(types, 0, 3, true);
147         list0 = list3;
148         delegateBooleanAssertion(types, 3, 0, true);
149         list4 = list0;
150         delegateBooleanAssertion(types, 0, 4, true);
151         list0 = list4;
152         delegateBooleanAssertion(types, 4, 0, true);
153         list5 = list0;
154         delegateBooleanAssertion(types, 0, 5, true);
155         list0 = list5;
156         delegateBooleanAssertion(types, 5, 0, true);
157         list6 = list0;
158         delegateBooleanAssertion(types, 0, 6, true);
159         list0 = list6;
160         delegateBooleanAssertion(types, 6, 0, true);
161 //        list1 = list1;
162         delegateBooleanAssertion(types, 1, 1, true);
163         list2 = list1;
164         delegateBooleanAssertion(types, 1, 2, true);
165         list1 = (List<Object>) list2;
166         delegateBooleanAssertion(types, 2, 1, false);
167         list3 = list1;
168         delegateBooleanAssertion(types, 1, 3, true);
169         list1 = (List<Object>) list3;
170         delegateBooleanAssertion(types, 3, 1, false);
171         // list4 = list1;
172         delegateBooleanAssertion(types, 1, 4, false);
173         // list1 = list4;
174         delegateBooleanAssertion(types, 4, 1, false);
175         // list5 = list1;
176         delegateBooleanAssertion(types, 1, 5, false);
177         // list1 = list5;
178         delegateBooleanAssertion(types, 5, 1, false);
179         list6 = list1;
180         delegateBooleanAssertion(types, 1, 6, true);
181         list1 = (List<Object>) list6;
182         delegateBooleanAssertion(types, 6, 1, false);
183 //        list2 = list2;
184         delegateBooleanAssertion(types, 2, 2, true);
185         list2 = list3;
186         delegateBooleanAssertion(types, 2, 3, false);
187         list2 = list4;
188         delegateBooleanAssertion(types, 3, 2, true);
189         list3 = (List<? super Object>) list2;
190         delegateBooleanAssertion(types, 2, 4, false);
191         list2 = list5;
192         delegateBooleanAssertion(types, 4, 2, true);
193         list4 = (List<String>) list2;
194         delegateBooleanAssertion(types, 2, 5, false);
195         list2 = list6;
196         delegateBooleanAssertion(types, 5, 2, true);
197         list5 = (List<? extends String>) list2;
198         delegateBooleanAssertion(types, 2, 6, false);
199 //        list3 = list3;
200         delegateBooleanAssertion(types, 6, 2, true);
201         list6 = (List<? super String>) list2;
202         delegateBooleanAssertion(types, 3, 3, true);
203         // list4 = list3;
204         delegateBooleanAssertion(types, 3, 4, false);
205         // list3 = list4;
206         delegateBooleanAssertion(types, 4, 3, false);
207         // list5 = list3;
208         delegateBooleanAssertion(types, 3, 5, false);
209         // list3 = list5;
210         delegateBooleanAssertion(types, 5, 3, false);
211         list6 = list3;
212         delegateBooleanAssertion(types, 3, 6, true);
213         list3 = (List<? super Object>) list6;
214         delegateBooleanAssertion(types, 6, 3, false);
215 //        list4 = list4;
216         delegateBooleanAssertion(types, 4, 4, true);
217         list5 = list4;
218         delegateBooleanAssertion(types, 4, 5, true);
219         list4 = (List<String>) list5;
220         delegateBooleanAssertion(types, 5, 4, false);
221         list6 = list4;
222         delegateBooleanAssertion(types, 4, 6, true);
223         list4 = (List<String>) list6;
224         delegateBooleanAssertion(types, 6, 4, false);
225 //        list5 = list5;
226         delegateBooleanAssertion(types, 5, 5, true);
227         list6 = (List<? super String>) list5;
228         delegateBooleanAssertion(types, 5, 6, false);
229         list5 = (List<? extends String>) list6;
230         delegateBooleanAssertion(types, 6, 5, false);
231 //        list6 = list6;
232         delegateBooleanAssertion(types, 6, 6, true);
233 
234 //        list7 = list7;
235         delegateBooleanAssertion(types, 7, 7, true);
236         list8 = list7;
237         delegateBooleanAssertion(types, 7, 8, true);
238         list7 = list8;
239         delegateBooleanAssertion(types, 8, 7, true);
240         list9 = list7;
241         delegateBooleanAssertion(types, 7, 9, true);
242         list7 = list9;
243         delegateBooleanAssertion(types, 9, 7, true);
244         list10 = list7;
245         delegateBooleanAssertion(types, 7, 10, true);
246         list7 = list10;
247         delegateBooleanAssertion(types, 10, 7, true);
248         list11 = list7;
249         delegateBooleanAssertion(types, 7, 11, true);
250         list7 = list11;
251         delegateBooleanAssertion(types, 11, 7, true);
252         list12 = list7;
253         delegateBooleanAssertion(types, 7, 12, true);
254         list7 = list12;
255         delegateBooleanAssertion(types, 12, 7, true);
256         list13 = list7;
257         delegateBooleanAssertion(types, 7, 13, true);
258         list7 = list13;
259         delegateBooleanAssertion(types, 13, 7, true);
260 //        list8 = list8;
261         delegateBooleanAssertion(types, 8, 8, true);
262         list9 = list8;
263         delegateBooleanAssertion(types, 8, 9, true);
264         list8 = (List<Object>[]) list9;
265         delegateBooleanAssertion(types, 9, 8, false);
266         list10 = list8;
267         delegateBooleanAssertion(types, 8, 10, true);
268         list8 = (List<Object>[]) list10; // NOTE cast is required by Sun Java, but not by Eclipse
269         delegateBooleanAssertion(types, 10, 8, false);
270         // list11 = list8;
271         delegateBooleanAssertion(types, 8, 11, false);
272         // list8 = list11;
273         delegateBooleanAssertion(types, 11, 8, false);
274         // list12 = list8;
275         delegateBooleanAssertion(types, 8, 12, false);
276         // list8 = list12;
277         delegateBooleanAssertion(types, 12, 8, false);
278         list13 = list8;
279         delegateBooleanAssertion(types, 8, 13, true);
280         list8 = (List<Object>[]) list13;
281         delegateBooleanAssertion(types, 13, 8, false);
282 //        list9 = list9;
283         delegateBooleanAssertion(types, 9, 9, true);
284         list10 = (List<? super Object>[]) list9;
285         delegateBooleanAssertion(types, 9, 10, false);
286         list9 = list10;
287         delegateBooleanAssertion(types, 10, 9, true);
288         list11 = (List<String>[]) list9;
289         delegateBooleanAssertion(types, 9, 11, false);
290         list9 = list11;
291         delegateBooleanAssertion(types, 11, 9, true);
292         list12 = (List<? extends String>[]) list9;
293         delegateBooleanAssertion(types, 9, 12, false);
294         list9 = list12;
295         delegateBooleanAssertion(types, 12, 9, true);
296         list13 = (List<? super String>[]) list9;
297         delegateBooleanAssertion(types, 9, 13, false);
298         list9 = list13;
299         delegateBooleanAssertion(types, 13, 9, true);
300 //        list10 = list10;
301         delegateBooleanAssertion(types, 10, 10, true);
302         // list11 = list10;
303         delegateBooleanAssertion(types, 10, 11, false);
304         // list10 = list11;
305         delegateBooleanAssertion(types, 11, 10, false);
306         // list12 = list10;
307         delegateBooleanAssertion(types, 10, 12, false);
308         // list10 = list12;
309         delegateBooleanAssertion(types, 12, 10, false);
310         list13 = list10;
311         delegateBooleanAssertion(types, 10, 13, true);
312         list10 = (List<? super Object>[]) list13;
313         delegateBooleanAssertion(types, 13, 10, false);
314 //        list11 = list11;
315         delegateBooleanAssertion(types, 11, 11, true);
316         list12 = list11;
317         delegateBooleanAssertion(types, 11, 12, true);
318         list11 = (List<String>[]) list12;
319         delegateBooleanAssertion(types, 12, 11, false);
320         list13 = list11;
321         delegateBooleanAssertion(types, 11, 13, true);
322         list11 = (List<String>[]) list13;
323         delegateBooleanAssertion(types, 13, 11, false);
324 //        list12 = list12;
325         delegateBooleanAssertion(types, 12, 12, true);
326         list13 = (List<? super String>[]) list12;
327         delegateBooleanAssertion(types, 12, 13, false);
328         list12 = (List<? extends String>[]) list13;
329         delegateBooleanAssertion(types, 13, 12, false);
330 //        list13 = list13;
331         delegateBooleanAssertion(types, 13, 13, true);
332         final Type disType = getClass().getField("dis").getGenericType();
333         // Reporter.log( ( ( ParameterizedType ) disType
334         // ).getOwnerType().getClass().toString() );
335         final Type datType = getClass().getField("dat").getGenericType();
336         final Type daType = getClass().getField("da").getGenericType();
337         final Type uhderType = getClass().getField("uhder").getGenericType();
338         final Type dingType = getClass().getField("ding").getGenericType();
339         final Type testerType = getClass().getField("tester").getGenericType();
340         final Type tester2Type = getClass().getField("tester2").getGenericType();
341         final Type dat2Type = getClass().getField("dat2").getGenericType();
342         final Type dat3Type = getClass().getField("dat3").getGenericType();
343         dis = dat;
344         Assert.assertTrue(TypeUtils.isAssignable(datType, disType));
345         // dis = da;
346         Assert.assertFalse(TypeUtils.isAssignable(daType, disType));
347         dis = uhder;
348         Assert.assertTrue(TypeUtils.isAssignable(uhderType, disType));
349         dis = ding;
350         Assert.assertFalse(String.format("type %s not assignable to %s!", dingType, disType),
351                 TypeUtils.isAssignable(dingType, disType));
352         dis = tester;
353         Assert.assertTrue(TypeUtils.isAssignable(testerType, disType));
354         // dis = tester2;
355         Assert.assertFalse(TypeUtils.isAssignable(tester2Type, disType));
356         // dat = dat2;
357         Assert.assertFalse(TypeUtils.isAssignable(dat2Type, datType));
358         // dat2 = dat;
359         Assert.assertFalse(TypeUtils.isAssignable(datType, dat2Type));
360         // dat = dat3;
361         Assert.assertFalse(TypeUtils.isAssignable(dat3Type, datType));
362         final char ch = 0;
363         final boolean bo = false;
364         final byte by = 0;
365         final short sh = 0;
366         int in = 0;
367         long lo = 0;
368         final float fl = 0;
369         double du = 0;
370         du = ch;
371         Assert.assertTrue(TypeUtils.isAssignable(char.class, double.class));
372         du = by;
373         Assert.assertTrue(TypeUtils.isAssignable(byte.class, double.class));
374         du = sh;
375         Assert.assertTrue(TypeUtils.isAssignable(short.class, double.class));
376         du = in;
377         Assert.assertTrue(TypeUtils.isAssignable(int.class, double.class));
378         du = lo;
379         Assert.assertTrue(TypeUtils.isAssignable(long.class, double.class));
380         du = fl;
381         Assert.assertTrue(TypeUtils.isAssignable(float.class, double.class));
382         lo = in;
383         Assert.assertTrue(TypeUtils.isAssignable(int.class, long.class));
384         lo = Integer.valueOf(0);
385         Assert.assertTrue(TypeUtils.isAssignable(Integer.class, long.class));
386         // Long lngW = 1;
387         Assert.assertFalse(TypeUtils.isAssignable(int.class, Long.class));
388         // lngW = Integer.valueOf( 0 );
389         Assert.assertFalse(TypeUtils.isAssignable(Integer.class, Long.class));
390         in = Integer.valueOf(0);
391         Assert.assertTrue(TypeUtils.isAssignable(Integer.class, int.class));
392         final Integer inte = in;
393         Assert.assertTrue(TypeUtils.isAssignable(int.class, Integer.class));
394         Assert.assertTrue(TypeUtils.isAssignable(int.class, Number.class));
395         Assert.assertTrue(TypeUtils.isAssignable(int.class, Object.class));
396         final Type intComparableType = getClass().getField("intComparable").getGenericType();
397         intComparable = 1;
398         Assert.assertTrue(TypeUtils.isAssignable(int.class, intComparableType));
399         Assert.assertTrue(TypeUtils.isAssignable(int.class, Comparable.class));
400         final Serializable ser = 1;
401         Assert.assertTrue(TypeUtils.isAssignable(int.class, Serializable.class));
402         final Type longComparableType = getClass().getField("longComparable").getGenericType();
403         // longComparable = 1;
404         Assert.assertFalse(TypeUtils.isAssignable(int.class, longComparableType));
405         // longComparable = Integer.valueOf( 0 );
406         Assert.assertFalse(TypeUtils.isAssignable(Integer.class, longComparableType));
407         // int[] ia;
408         // long[] la = ia;
409         Assert.assertFalse(TypeUtils.isAssignable(int[].class, long[].class));
410         final Integer[] ia = null;
411         final Type caType = getClass().getField("intWildcardComparable").getGenericType();
412         intWildcardComparable = ia;
413         Assert.assertTrue(TypeUtils.isAssignable(Integer[].class, caType));
414         // int[] ina = ia;
415         Assert.assertFalse(TypeUtils.isAssignable(Integer[].class, int[].class));
416         final int[] ina = null;
417         Object[] oa;
418         // oa = ina;
419         Assert.assertFalse(TypeUtils.isAssignable(int[].class, Object[].class));
420         oa = new Integer[0];
421         Assert.assertTrue(TypeUtils.isAssignable(Integer[].class, Object[].class));
422         final Type bClassType = AClass.class.getField("bClass").getGenericType();
423         final Type cClassType = AClass.class.getField("cClass").getGenericType();
424         final Type dClassType = AClass.class.getField("dClass").getGenericType();
425         final Type eClassType = AClass.class.getField("eClass").getGenericType();
426         final Type fClassType = AClass.class.getField("fClass").getGenericType();
427         final AClass aClass = new AClass(new AAClass<String>());
428         aClass.bClass = aClass.cClass;
429         Assert.assertTrue(TypeUtils.isAssignable(cClassType, bClassType));
430         aClass.bClass = aClass.dClass;
431         Assert.assertTrue(TypeUtils.isAssignable(dClassType, bClassType));
432         aClass.bClass = aClass.eClass;
433         Assert.assertTrue(TypeUtils.isAssignable(eClassType, bClassType));
434         aClass.bClass = aClass.fClass;
435         Assert.assertTrue(TypeUtils.isAssignable(fClassType, bClassType));
436         aClass.cClass = aClass.dClass;
437         Assert.assertTrue(TypeUtils.isAssignable(dClassType, cClassType));
438         aClass.cClass = aClass.eClass;
439         Assert.assertTrue(TypeUtils.isAssignable(eClassType, cClassType));
440         aClass.cClass = aClass.fClass;
441         Assert.assertTrue(TypeUtils.isAssignable(fClassType, cClassType));
442         aClass.dClass = aClass.eClass;
443         Assert.assertTrue(TypeUtils.isAssignable(eClassType, dClassType));
444         aClass.dClass = aClass.fClass;
445         Assert.assertTrue(TypeUtils.isAssignable(fClassType, dClassType));
446         aClass.eClass = aClass.fClass;
447         Assert.assertTrue(TypeUtils.isAssignable(fClassType, eClassType));
448     }
449 
450     public void delegateBooleanAssertion(final Type[] types, final int i2, final int i1, final boolean expected) {
451         final Type type1 = types[i1];
452         final Type type2 = types[i2];
453         final boolean isAssignable = TypeUtils.isAssignable(type2, type1);
454 
455         if (expected) {
456             Assert.assertTrue("[" + i1 + ", " + i2 + "]: From "
457                     + String.valueOf(type2) + " to "
458                     + String.valueOf(type1), isAssignable);
459         } else {
460             Assert.assertFalse("[" + i1 + ", " + i2 + "]: From "
461                     + String.valueOf(type2) + " to "
462                     + String.valueOf(type1), isAssignable);
463         }
464     }
465 
466     @SuppressWarnings("boxing") // boxing is deliberate here
467     @Test
468     public void testIsInstance() throws SecurityException, NoSuchFieldException {
469         final Type intComparableType = getClass().getField("intComparable").getGenericType();
470         final Type uriComparableType = getClass().getField("uriComparable").getGenericType();
471         intComparable = 1;
472         Assert.assertTrue(TypeUtils.isInstance(1, intComparableType));
473         // uriComparable = 1;
474         Assert.assertFalse(TypeUtils.isInstance(1, uriComparableType));
475     }
476 
477     @Test
478     public void testGetTypeArguments() {
479         Map<TypeVariable<?>, Type> typeVarAssigns;
480         TypeVariable<?> treeSetTypeVar;
481         Type typeArg;
482 
483         typeVarAssigns = TypeUtils.getTypeArguments(Integer.class, Comparable.class);
484         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
485         Assert.assertTrue("Type var assigns for Comparable from Integer: " + typeVarAssigns,
486                 typeVarAssigns.containsKey(treeSetTypeVar));
487         typeArg = typeVarAssigns.get(treeSetTypeVar);
488         Assert.assertEquals("Type argument of Comparable from Integer: " + typeArg, Integer.class,
489                 typeVarAssigns.get(treeSetTypeVar));
490 
491         typeVarAssigns = TypeUtils.getTypeArguments(int.class, Comparable.class);
492         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
493         Assert.assertTrue("Type var assigns for Comparable from int: " + typeVarAssigns,
494                 typeVarAssigns.containsKey(treeSetTypeVar));
495         typeArg = typeVarAssigns.get(treeSetTypeVar);
496         Assert.assertEquals("Type argument of Comparable from int: " + typeArg, Integer.class,
497                 typeVarAssigns.get(treeSetTypeVar));
498 
499         final Collection<Integer> col = Arrays.asList(new Integer[0]);
500         typeVarAssigns = TypeUtils.getTypeArguments(List.class, Collection.class);
501         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
502         Assert.assertFalse("Type var assigns for Collection from List: " + typeVarAssigns,
503                 typeVarAssigns.containsKey(treeSetTypeVar));
504 
505         typeVarAssigns = TypeUtils.getTypeArguments(AAAClass.BBBClass.class, AAClass.BBClass.class);
506         Assert.assertTrue(typeVarAssigns.size() == 2);
507         Assert.assertEquals(String.class, typeVarAssigns.get(AAClass.class.getTypeParameters()[0]));
508         Assert.assertEquals(String.class, typeVarAssigns.get(AAClass.BBClass.class.getTypeParameters()[0]));
509 
510         typeVarAssigns = TypeUtils.getTypeArguments(Other.class, This.class);
511         Assert.assertEquals(2, typeVarAssigns.size());
512         Assert.assertEquals(String.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
513         Assert.assertEquals(Other.class.getTypeParameters()[0], typeVarAssigns.get(This.class.getTypeParameters()[1]));
514 
515         typeVarAssigns = TypeUtils.getTypeArguments(And.class, This.class);
516         Assert.assertEquals(2, typeVarAssigns.size());
517         Assert.assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
518         Assert.assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[1]));
519 
520         typeVarAssigns = TypeUtils.getTypeArguments(Thing.class, Other.class);
521         Assert.assertEquals(2, typeVarAssigns.size());
522         Assert.assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(getClass().getTypeParameters()[0]));
523         Assert.assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(Other.class.getTypeParameters()[0]));
524     }
525 
526     @Test
527     public void testTypesSatisfyVariables() throws SecurityException, NoSuchFieldException,
528             NoSuchMethodException {
529         final Map<TypeVariable<?>, Type> typeVarAssigns = new HashMap<>();
530         final Integer max = TypeUtilsTest.<Integer> stub();
531         typeVarAssigns.put(getClass().getMethod("stub").getTypeParameters()[0], Integer.class);
532         Assert.assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
533         typeVarAssigns.clear();
534         typeVarAssigns.put(getClass().getMethod("stub2").getTypeParameters()[0], Integer.class);
535         Assert.assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
536         typeVarAssigns.clear();
537         typeVarAssigns.put(getClass().getMethod("stub3").getTypeParameters()[0], Integer.class);
538         Assert.assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
539     }
540 
541     @Test
542     public void testDetermineTypeVariableAssignments() throws SecurityException,
543             NoSuchFieldException, NoSuchMethodException {
544         final ParameterizedType iterableType = (ParameterizedType) getClass().getField("iterable")
545                 .getGenericType();
546         final Map<TypeVariable<?>, Type> typeVarAssigns = TypeUtils.determineTypeArguments(TreeSet.class,
547                 iterableType);
548         final TypeVariable<?> treeSetTypeVar = TreeSet.class.getTypeParameters()[0];
549         Assert.assertTrue(typeVarAssigns.containsKey(treeSetTypeVar));
550         Assert.assertEquals(iterableType.getActualTypeArguments()[0], typeVarAssigns
551                 .get(treeSetTypeVar));
552     }
553 
554     @Test
555     public void testGetRawType() throws SecurityException, NoSuchFieldException {
556         final Type stringParentFieldType = GenericTypeHolder.class.getDeclaredField("stringParent")
557                 .getGenericType();
558         final Type integerParentFieldType = GenericTypeHolder.class.getDeclaredField("integerParent")
559                 .getGenericType();
560         final Type foosFieldType = GenericTypeHolder.class.getDeclaredField("foos").getGenericType();
561         final Type genericParentT = GenericParent.class.getTypeParameters()[0];
562         Assert.assertEquals(GenericParent.class, TypeUtils.getRawType(stringParentFieldType, null));
563         Assert
564                 .assertEquals(GenericParent.class, TypeUtils.getRawType(integerParentFieldType,
565                         null));
566         Assert.assertEquals(List.class, TypeUtils.getRawType(foosFieldType, null));
567         Assert.assertEquals(String.class, TypeUtils.getRawType(genericParentT,
568                 StringParameterizedChild.class));
569         Assert.assertEquals(String.class, TypeUtils.getRawType(genericParentT,
570                 stringParentFieldType));
571         Assert.assertEquals(Foo.class, TypeUtils.getRawType(Iterable.class.getTypeParameters()[0],
572                 foosFieldType));
573         Assert.assertEquals(Foo.class, TypeUtils.getRawType(List.class.getTypeParameters()[0],
574                 foosFieldType));
575         Assert.assertNull(TypeUtils.getRawType(genericParentT, GenericParent.class));
576         Assert.assertEquals(GenericParent[].class, TypeUtils.getRawType(GenericTypeHolder.class
577                 .getDeclaredField("barParents").getGenericType(), null));
578     }
579 
580     @Test
581     public void testIsArrayTypeClasses() {
582         Assert.assertTrue(TypeUtils.isArrayType(boolean[].class));
583         Assert.assertTrue(TypeUtils.isArrayType(byte[].class));
584         Assert.assertTrue(TypeUtils.isArrayType(short[].class));
585         Assert.assertTrue(TypeUtils.isArrayType(int[].class));
586         Assert.assertTrue(TypeUtils.isArrayType(char[].class));
587         Assert.assertTrue(TypeUtils.isArrayType(long[].class));
588         Assert.assertTrue(TypeUtils.isArrayType(float[].class));
589         Assert.assertTrue(TypeUtils.isArrayType(double[].class));
590         Assert.assertTrue(TypeUtils.isArrayType(Object[].class));
591         Assert.assertTrue(TypeUtils.isArrayType(String[].class));
592 
593         Assert.assertFalse(TypeUtils.isArrayType(boolean.class));
594         Assert.assertFalse(TypeUtils.isArrayType(byte.class));
595         Assert.assertFalse(TypeUtils.isArrayType(short.class));
596         Assert.assertFalse(TypeUtils.isArrayType(int.class));
597         Assert.assertFalse(TypeUtils.isArrayType(char.class));
598         Assert.assertFalse(TypeUtils.isArrayType(long.class));
599         Assert.assertFalse(TypeUtils.isArrayType(float.class));
600         Assert.assertFalse(TypeUtils.isArrayType(double.class));
601         Assert.assertFalse(TypeUtils.isArrayType(Object.class));
602         Assert.assertFalse(TypeUtils.isArrayType(String.class));
603     }
604 
605     @Test
606     public void testIsArrayGenericTypes() throws Exception {
607         final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
608                 List.class, List.class, List.class, List.class, List[].class, List[].class,
609                 List[].class, List[].class, List[].class, List[].class, List[].class);
610 
611         final Type[] types = method.getGenericParameterTypes();
612 
613         Assert.assertFalse(TypeUtils.isArrayType(types[0]));
614         Assert.assertFalse(TypeUtils.isArrayType(types[1]));
615         Assert.assertFalse(TypeUtils.isArrayType(types[2]));
616         Assert.assertFalse(TypeUtils.isArrayType(types[3]));
617         Assert.assertFalse(TypeUtils.isArrayType(types[4]));
618         Assert.assertFalse(TypeUtils.isArrayType(types[5]));
619         Assert.assertFalse(TypeUtils.isArrayType(types[6]));
620         Assert.assertTrue(TypeUtils.isArrayType(types[7]));
621         Assert.assertTrue(TypeUtils.isArrayType(types[8]));
622         Assert.assertTrue(TypeUtils.isArrayType(types[9]));
623         Assert.assertTrue(TypeUtils.isArrayType(types[10]));
624         Assert.assertTrue(TypeUtils.isArrayType(types[11]));
625         Assert.assertTrue(TypeUtils.isArrayType(types[12]));
626         Assert.assertTrue(TypeUtils.isArrayType(types[13]));
627     }
628 
629     @Test
630     public void testGetPrimitiveArrayComponentType() throws Exception {
631         Assert.assertEquals(boolean.class, TypeUtils.getArrayComponentType(boolean[].class));
632         Assert.assertEquals(byte.class, TypeUtils.getArrayComponentType(byte[].class));
633         Assert.assertEquals(short.class, TypeUtils.getArrayComponentType(short[].class));
634         Assert.assertEquals(int.class, TypeUtils.getArrayComponentType(int[].class));
635         Assert.assertEquals(char.class, TypeUtils.getArrayComponentType(char[].class));
636         Assert.assertEquals(long.class, TypeUtils.getArrayComponentType(long[].class));
637         Assert.assertEquals(float.class, TypeUtils.getArrayComponentType(float[].class));
638         Assert.assertEquals(double.class, TypeUtils.getArrayComponentType(double[].class));
639 
640         Assert.assertNull(TypeUtils.getArrayComponentType(boolean.class));
641         Assert.assertNull(TypeUtils.getArrayComponentType(byte.class));
642         Assert.assertNull(TypeUtils.getArrayComponentType(short.class));
643         Assert.assertNull(TypeUtils.getArrayComponentType(int.class));
644         Assert.assertNull(TypeUtils.getArrayComponentType(char.class));
645         Assert.assertNull(TypeUtils.getArrayComponentType(long.class));
646         Assert.assertNull(TypeUtils.getArrayComponentType(float.class));
647         Assert.assertNull(TypeUtils.getArrayComponentType(double.class));
648     }
649 
650     @Test
651     public void testGetArrayComponentType() throws Exception {
652         final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
653                 List.class, List.class, List.class, List.class, List[].class, List[].class,
654                 List[].class, List[].class, List[].class, List[].class, List[].class);
655 
656         final Type[] types = method.getGenericParameterTypes();
657 
658         Assert.assertNull(TypeUtils.getArrayComponentType(types[0]));
659         Assert.assertNull(TypeUtils.getArrayComponentType(types[1]));
660         Assert.assertNull(TypeUtils.getArrayComponentType(types[2]));
661         Assert.assertNull(TypeUtils.getArrayComponentType(types[3]));
662         Assert.assertNull(TypeUtils.getArrayComponentType(types[4]));
663         Assert.assertNull(TypeUtils.getArrayComponentType(types[5]));
664         Assert.assertNull(TypeUtils.getArrayComponentType(types[6]));
665         Assert.assertEquals(types[0], TypeUtils.getArrayComponentType(types[7]));
666         Assert.assertEquals(types[1], TypeUtils.getArrayComponentType(types[8]));
667         Assert.assertEquals(types[2], TypeUtils.getArrayComponentType(types[9]));
668         Assert.assertEquals(types[3], TypeUtils.getArrayComponentType(types[10]));
669         Assert.assertEquals(types[4], TypeUtils.getArrayComponentType(types[11]));
670         Assert.assertEquals(types[5], TypeUtils.getArrayComponentType(types[12]));
671         Assert.assertEquals(types[6], TypeUtils.getArrayComponentType(types[13]));
672     }
673 
674     @Test
675     public void testLang820() throws Exception {
676         final Type[] typeArray = {String.class, String.class};
677         final Type[] expectedArray = {String.class};
678         Assert.assertArrayEquals(expectedArray, TypeUtils.normalizeUpperBounds(typeArray));
679     }
680 
681     @Test
682     public void testParameterize() throws Exception {
683         final ParameterizedType stringComparableType = TypeUtils.parameterize(Comparable.class, String.class);
684         Assert.assertTrue(TypeUtils.equals(getClass().getField("stringComparable").getGenericType(),
685             stringComparableType));
686         Assert.assertEquals("java.lang.Comparable<java.lang.String>", stringComparableType.toString());
687     }
688 
689     @Test
690     public void testParameterizeWithOwner() throws Exception {
691         final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
692         final ParameterizedType dat2Type = TypeUtils.parameterizeWithOwner(owner, That.class, String.class, String.class);
693         Assert.assertTrue(TypeUtils.equals(getClass().getField("dat2").getGenericType(), dat2Type));
694     }
695 
696     @Test
697     public void testWildcardType() throws Exception {
698         final WildcardType simpleWildcard = TypeUtils.wildcardType().withUpperBounds(String.class).build();
699         final Field cClass = AClass.class.getField("cClass");
700         Assert.assertTrue(TypeUtils.equals(((ParameterizedType) cClass.getGenericType()).getActualTypeArguments()[0],
701             simpleWildcard));
702         Assert.assertEquals(String.format("? extends %s", String.class.getName()), TypeUtils.toString(simpleWildcard));
703         Assert.assertEquals(String.format("? extends %s", String.class.getName()), simpleWildcard.toString());
704     }
705 
706     @Test
707     public void testUnboundedWildcardType() {
708         final WildcardType unbounded = TypeUtils.wildcardType().withLowerBounds((Type) null).withUpperBounds().build();
709         Assert.assertTrue(TypeUtils.equals(TypeUtils.WILDCARD_ALL, unbounded));
710         Assert.assertArrayEquals(new Type[] { Object.class }, TypeUtils.getImplicitUpperBounds(unbounded));
711         Assert.assertArrayEquals(new Type[] { null }, TypeUtils.getImplicitLowerBounds(unbounded));
712         Assert.assertEquals("?", TypeUtils.toString(unbounded));
713         Assert.assertEquals("?", unbounded.toString());
714     }
715 
716     @Test
717     public void testLowerBoundedWildcardType() {
718        final WildcardType lowerBounded = TypeUtils.wildcardType().withLowerBounds(java.sql.Date.class).build();
719        Assert.assertEquals(String.format("? super %s", java.sql.Date.class.getName()), TypeUtils.toString(lowerBounded));
720        Assert.assertEquals(String.format("? super %s", java.sql.Date.class.getName()), lowerBounded.toString());
721 
722        final TypeVariable<Class<Iterable>> iterableT0 = Iterable.class.getTypeParameters()[0];
723        final WildcardType lowerTypeVariable = TypeUtils.wildcardType().withLowerBounds(iterableT0).build();
724        Assert.assertEquals(String.format("? super %s", iterableT0.getName()), TypeUtils.toString(lowerTypeVariable));
725        Assert.assertEquals(String.format("? super %s", iterableT0.getName()), lowerTypeVariable.toString());
726     }
727 
728     @Test
729     public void testLang1114() throws Exception {
730         final Type nonWildcardType = getClass().getDeclaredField("wildcardComparable").getGenericType();
731         final Type wildcardType = ((ParameterizedType)nonWildcardType).getActualTypeArguments()[0];
732 
733         Assert.assertFalse(TypeUtils.equals(wildcardType, nonWildcardType));
734         Assert.assertFalse(TypeUtils.equals(nonWildcardType, wildcardType));
735     }
736 
737     @Test
738     public void testGenericArrayType() throws Exception {
739         final Type expected = getClass().getField("intWildcardComparable").getGenericType();
740         final GenericArrayType actual =
741             TypeUtils.genericArrayType(TypeUtils.parameterize(Comparable.class, TypeUtils.wildcardType()
742                 .withUpperBounds(Integer.class).build()));
743         Assert.assertTrue(TypeUtils.equals(expected, actual));
744         Assert.assertEquals("java.lang.Comparable<? extends java.lang.Integer>[]", actual.toString());
745     }
746 
747     @Test
748     public void testToStringLang1311() {
749         Assert.assertEquals("int[]", TypeUtils.toString(int[].class));
750         Assert.assertEquals("java.lang.Integer[]", TypeUtils.toString(Integer[].class));
751         Field stringListField = FieldUtils.getDeclaredField(getClass(), "stringListArray");
752         Assert.assertEquals("java.util.List<java.lang.String>[]", TypeUtils.toString(stringListField.getGenericType()));
753     }
754 
755     @Test
756     public void testToLongString() {
757         Assert.assertEquals(getClass().getName() + ":B", TypeUtils.toLongString(getClass().getTypeParameters()[0]));
758     }
759 
760     @Test
761     public void testWrap() {
762         final Type t = getClass().getTypeParameters()[0];
763         Assert.assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
764 
765         Assert.assertEquals(String.class, TypeUtils.wrap(String.class).getType());
766     }
767 
768     public static class ClassWithSuperClassWithGenericType extends ArrayList<Object> {
769         private static final long serialVersionUID = 1L;
770 
771         public static <U> Iterable<U> methodWithGenericReturnType() {
772             return null;
773         }
774     }
775 
776     @Test
777     public void testLANG1190() throws Exception {
778         final Type fromType = ClassWithSuperClassWithGenericType.class.getDeclaredMethod("methodWithGenericReturnType").getGenericReturnType();
779         final Type failingToType = TypeUtils.wildcardType().withLowerBounds(ClassWithSuperClassWithGenericType.class).build();
780 
781         Assert.assertTrue(TypeUtils.isAssignable(fromType, failingToType));
782     }
783 
784     public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
785 
786     public static <G extends Comparable<G>> G stub() {
787         return null;
788     }
789 
790     public static <G extends Comparable<? super G>> G stub2() {
791         return null;
792     }
793 
794     public static <T extends Comparable<? extends T>> T stub3() {
795         return null;
796     }
797 }
798 
799 class AAClass<T> {
800 
801     public class BBClass<S> {
802     }
803 }
804 
805 class AAAClass extends AAClass<String> {
806     public class BBBClass extends BBClass<String> {
807     }
808 }
809 
810 @SuppressWarnings("rawtypes")
811 //raw types, where used, are used purposely
812 class AClass extends AAClass<String>.BBClass<Number> {
813 
814     AClass(final AAClass<String> enclosingInstance) {
815         enclosingInstance.super();
816     }
817 
818     public class BClass<T> {
819     }
820 
821     public class CClass<T> extends BClass {
822     }
823 
824     public class DClass<T> extends CClass<T> {
825     }
826 
827     public class EClass<T> extends DClass {
828     }
829 
830     public class FClass extends EClass<String> {
831     }
832 
833     public class GClass<T extends BClass<? extends T> & AInterface<AInterface<? super T>>> {
834     }
835 
836     public BClass<Number> bClass;
837 
838     public CClass<? extends String> cClass;
839 
840     public DClass<String> dClass;
841 
842     public EClass<String> eClass;
843 
844     public FClass fClass;
845 
846     public GClass gClass;
847 
848     public interface AInterface<T> {
849     }
850 }