1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package tests.api.java.lang.reflect;
18
19
20import java.lang.reflect.Method;
21import java.lang.reflect.ParameterizedType;
22import java.lang.reflect.Type;
23import java.lang.reflect.TypeVariable;
24import java.lang.reflect.WildcardType;
25
26/**
27 * Tests bounded type parameters declared on methods and bounded wildcards.
28 */
29public class WildcardTypeTest extends GenericReflectionTestsBase {
30    @SuppressWarnings({"unchecked", "hiding"})
31    static class BoundedWildcardsGenericMethods<T> {
32
33        public <T extends BoundedWildcardsGenericMethods> void lowerBoundedParamNoReturn( BoundedWildcardsGenericMethods<? super T> param) {}
34
35        public <T extends BoundedWildcardsGenericMethods> void upperBoundedParamNoReturn( BoundedWildcardsGenericMethods<? extends T> param) {}
36
37        public <T extends BoundedWildcardsGenericMethods> T lowerBoundedParamReturn(BoundedWildcardsGenericMethods<? super T> param) { return (T) new Object(); }
38
39        public <T extends BoundedWildcardsGenericMethods> T upperBoundedParamReturn(BoundedWildcardsGenericMethods<? extends T> param) { return (T) new Object();}
40    }
41
42    @SuppressWarnings("unchecked")
43    private static Class<? extends BoundedWildcardsGenericMethods> clazz = BoundedWildcardsGenericMethods.class;
44
45    /**
46     * Tests that there are is one Type Parameter on the Class itself.
47     */
48    public void testBoundedGenericMethods() {
49        assertLenghtOne(clazz.getTypeParameters());
50    }
51
52    /**
53     * Tests whether the type parameter is bounded by BoundedGenericMethods like:
54     * <T extends BoundedGenericMethods>.
55     * @param method the declaring method
56     */
57    private void checkBoundedTypeParameter(Method method) {
58        TypeVariable<Method> typeParameter = getTypeParameter(method);
59        assertEquals("T", typeParameter.getName());
60        assertEquals(method, typeParameter.getGenericDeclaration());
61
62        Type[] bounds = typeParameter.getBounds();
63        assertLenghtOne(bounds);
64        Type bound = bounds[0];
65        assertEquals(BoundedWildcardsGenericMethods.class, bound);
66    }
67
68    private void checkLowerBoundedParameter(Method method) {
69        Type genericParameterType = method.getGenericParameterTypes()[0];
70        assertInstanceOf(ParameterizedType.class, genericParameterType);
71
72        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
73
74        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
75        assertLenghtOne(actualTypeArguments);
76        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);
77
78        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
79
80        Type[] lowerBounds = wildcardType.getLowerBounds();
81        assertLenghtOne(lowerBounds);
82        Type lowerBound = lowerBounds[0];
83        assertEquals(getTypeParameter(method), lowerBound);
84
85        Type[] upperBounds = wildcardType.getUpperBounds();
86        assertEquals(Object.class, upperBounds[0]);
87    }
88
89    private void checkUpperBoundedParameter(Method method) {
90        assertLenghtOne(method.getGenericParameterTypes());
91        Type genericParameterType = method.getGenericParameterTypes()[0];
92        assertInstanceOf(ParameterizedType.class, genericParameterType);
93
94        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
95        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
96        assertLenghtOne(actualTypeArguments);
97        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);
98
99        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
100        assertLenghtZero(wildcardType.getLowerBounds());
101
102        Type[] upperBounds = wildcardType.getUpperBounds();
103        assertLenghtOne(upperBounds);
104        Type upperBound = upperBounds[0];
105        assertEquals(getTypeParameter(method), upperBound);
106    }
107
108    @SuppressWarnings("unchecked")
109    private void checkReturnType(Method method) {
110        Type genericReturnType = method.getGenericReturnType();
111        assertEquals(getTypeParameter(method), genericReturnType);
112        assertTrue(genericReturnType instanceof TypeVariable);
113
114        TypeVariable<Method> returnTypeVariable = (TypeVariable<Method>) genericReturnType;
115        assertEquals(method, returnTypeVariable.getGenericDeclaration());
116
117        Type[] bounds = returnTypeVariable.getBounds();
118        assertLenghtOne(bounds);
119        Type bound = bounds[0];
120
121        assertEquals(BoundedWildcardsGenericMethods.class, bound);
122    }
123
124    public void testUpperBoundedParamNoReturn() throws Exception {
125        Method method = clazz.getMethod("upperBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
126        checkBoundedTypeParameter(method);
127        checkUpperBoundedParameter(method);
128    }
129
130    public void testLowerBoundedParamReturn() throws Exception {
131        Method method = clazz.getMethod("lowerBoundedParamReturn", BoundedWildcardsGenericMethods.class);
132        checkBoundedTypeParameter(method);
133        checkLowerBoundedParameter(method);
134        checkReturnType(method);
135    }
136
137    public void testUpperBoundedParamReturn() throws Exception {
138        Method method = clazz.getMethod("upperBoundedParamReturn", BoundedWildcardsGenericMethods.class);
139        checkBoundedTypeParameter(method);
140        checkUpperBoundedParameter(method);
141        checkReturnType(method);
142    }
143
144    public void testLowerBoundedParamNoReturn() throws Exception {
145        Method method = clazz.getMethod("lowerBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
146        checkBoundedTypeParameter(method);
147        assertLenghtOne(method.getGenericParameterTypes());
148        checkLowerBoundedParameter(method);
149    }
150
151}
152