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