/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.harmony.tests.java.lang.reflect;


import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;

/**
 * Tests bounded type parameters declared on methods and bounded wildcards.
 */
public class WildcardTypeTest extends GenericReflectionTestsBase {
    @SuppressWarnings({"unchecked", "hiding"})
    static class BoundedWildcardsGenericMethods<T> {

        public <T extends BoundedWildcardsGenericMethods> void lowerBoundedParamNoReturn( BoundedWildcardsGenericMethods<? super T> param) {}

        public <T extends BoundedWildcardsGenericMethods> void upperBoundedParamNoReturn( BoundedWildcardsGenericMethods<? extends T> param) {}

        public <T extends BoundedWildcardsGenericMethods> T lowerBoundedParamReturn(BoundedWildcardsGenericMethods<? super T> param) { return (T) new Object(); }

        public <T extends BoundedWildcardsGenericMethods> T upperBoundedParamReturn(BoundedWildcardsGenericMethods<? extends T> param) { return (T) new Object();}
    }

    @SuppressWarnings("unchecked")
    private static Class<? extends BoundedWildcardsGenericMethods> clazz = BoundedWildcardsGenericMethods.class;

    /**
     * Tests that there are is one Type Parameter on the Class itself.
     */
    public void testBoundedGenericMethods() {
        assertLenghtOne(clazz.getTypeParameters());
    }

    /**
     * Tests whether the type parameter is bounded by BoundedGenericMethods like:
     * <T extends BoundedGenericMethods>.
     * @param method the declaring method
     */
    private void checkBoundedTypeParameter(Method method) {
        TypeVariable<Method> typeParameter = getTypeParameter(method);
        assertEquals("T", typeParameter.getName());
        assertEquals(method, typeParameter.getGenericDeclaration());

        Type[] bounds = typeParameter.getBounds();
        assertLenghtOne(bounds);
        Type bound = bounds[0];
        assertEquals(BoundedWildcardsGenericMethods.class, bound);
    }

    private void checkLowerBoundedParameter(Method method) {
        Type genericParameterType = method.getGenericParameterTypes()[0];
        assertInstanceOf(ParameterizedType.class, genericParameterType);

        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;

        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        assertLenghtOne(actualTypeArguments);
        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);

        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
        assertEquals("? super T", wildcardType.toString());
        assertEquals("? super T", wildcardType.getTypeName());

        Type[] lowerBounds = wildcardType.getLowerBounds();
        assertLenghtOne(lowerBounds);
        Type lowerBound = lowerBounds[0];
        assertEquals(getTypeParameter(method), lowerBound);

        Type[] upperBounds = wildcardType.getUpperBounds();
        assertEquals(Object.class, upperBounds[0]);
    }

    private void checkUpperBoundedParameter(Method method) {
        assertLenghtOne(method.getGenericParameterTypes());
        Type genericParameterType = method.getGenericParameterTypes()[0];
        assertInstanceOf(ParameterizedType.class, genericParameterType);

        ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
        assertLenghtOne(actualTypeArguments);
        assertInstanceOf(WildcardType.class, actualTypeArguments[0]);

        WildcardType wildcardType = (WildcardType) actualTypeArguments[0];
        assertEquals("? extends T", wildcardType.toString());
        assertEquals("? extends T", wildcardType.getTypeName());
        assertLenghtZero(wildcardType.getLowerBounds());

        Type[] upperBounds = wildcardType.getUpperBounds();
        assertLenghtOne(upperBounds);
        Type upperBound = upperBounds[0];
        assertEquals(getTypeParameter(method), upperBound);
    }

    @SuppressWarnings("unchecked")
    private void checkReturnType(Method method) {
        Type genericReturnType = method.getGenericReturnType();
        assertEquals(getTypeParameter(method), genericReturnType);
        assertTrue(genericReturnType instanceof TypeVariable);

        TypeVariable<Method> returnTypeVariable = (TypeVariable<Method>) genericReturnType;
        assertEquals(method, returnTypeVariable.getGenericDeclaration());

        Type[] bounds = returnTypeVariable.getBounds();
        assertLenghtOne(bounds);
        Type bound = bounds[0];

        assertEquals(BoundedWildcardsGenericMethods.class, bound);
    }

    public void testUpperBoundedParamNoReturn() throws Exception {
        Method method = clazz.getMethod("upperBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
        checkBoundedTypeParameter(method);
        checkUpperBoundedParameter(method);
    }

    public void testLowerBoundedParamReturn() throws Exception {
        Method method = clazz.getMethod("lowerBoundedParamReturn", BoundedWildcardsGenericMethods.class);
        checkBoundedTypeParameter(method);
        checkLowerBoundedParameter(method);
        checkReturnType(method);
    }

    public void testUpperBoundedParamReturn() throws Exception {
        Method method = clazz.getMethod("upperBoundedParamReturn", BoundedWildcardsGenericMethods.class);
        checkBoundedTypeParameter(method);
        checkUpperBoundedParameter(method);
        checkReturnType(method);
    }

    public void testLowerBoundedParamNoReturn() throws Exception {
        Method method = clazz.getMethod("lowerBoundedParamNoReturn", BoundedWildcardsGenericMethods.class);
        checkBoundedTypeParameter(method);
        assertLenghtOne(method.getGenericParameterTypes());
        checkLowerBoundedParameter(method);
    }

}
