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