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