Package com.alibaba.citrus.generictype

Source Code of com.alibaba.citrus.generictype.MyClass2

/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.citrus.generictype;

import static com.alibaba.citrus.generictype.TypeInfo.*;
import static com.alibaba.citrus.test.TestUtil.*;
import static org.junit.Assert.*;

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.junit.Test;

/**
* 综合测试。
*
* @author Michael Zhou
*/
public class TypeInfoFactoryTests {
    @Test(expected = IllegalArgumentException.class)
    public void getClass_array() {
        factory.getClassType(int[].class);
    }

    @Test
    public void getClass_rawClass() {
        assertSame(factory.getType(int.class), factory.getClassType(int.class));
        assertSame(factory.getType(String.class), factory.getClassType(String.class));
        assertSame(factory.getType(List.class), factory.getClassType(List.class));

        assertSame(factory.getGenericDeclaration(int.class), factory.getClassType(int.class));
        assertSame(factory.getGenericDeclaration(String.class), factory.getClassType(String.class));
        assertSame(factory.getGenericDeclaration(List.class), factory.getClassType(List.class));
    }

    @Test
    public void getClass_parameterizedClass() {
        class StringList extends ArrayList<String> {
            private static final long serialVersionUID = -6675085611077625191L;
        }

        ParameterizedType type = (ParameterizedType) StringList.class.getGenericSuperclass();

        assertEquals(factory.getType(type), factory.getClassType(type));
    }

    @Test(expected = IllegalArgumentException.class)
    public void getGenericDeclaration_arrayClass() {
        factory.getGenericDeclaration(Integer[][].class);
    }

    @Test
    public void getMethod() {
        for (Method method : TypeInfoFactoryTests.class.getMethods()) {
            assertEquals(factory.getGenericDeclaration(method), factory.getMethod(method));
        }
    }

    @Test
    public void getConstructorMethod() {
        for (Constructor<?> constructor : ArrayList.class.getConstructors()) {
            assertEquals(factory.getGenericDeclaration(constructor), factory.getConstructor(constructor));
        }
    }

    @Test
    public void getParameterizedType() {
        ParameterizedTypeInfo type1 = factory.getParameterizedType(List.class, String.class);
        ParameterizedTypeInfo type2 = factory.getParameterizedType(factory.getClassType(List.class), String.class);
        ParameterizedTypeInfo type3 = factory.getParameterizedType(factory.getClassType(List.class),
                                                                   factory.getClassType(String.class));

        assertEquals(type1, type2);
        assertEquals(type2, type3);
    }

    @Test
    public void getArrayType() {
        ArrayTypeInfo ati1 = factory.getArrayType(String.class, 2);
        ArrayTypeInfo ati2 = factory.getArrayType(factory.getType(String.class), 2);

        assertSame(ati1, ati2);
    }

    /** 递归创建types的情形。 */
    @Test
    public void recursiveType() {
        RawTypeInfo layout = (RawTypeInfo) factory.getType(Layout.class);
        ParameterizedTypeInfo pt_layout = (ParameterizedTypeInfo) layout.getTypeParameters().get(0).getBaseType();

        assertSame(layout.getRawType(), pt_layout.getRawType());

        RawTypeInfo layoutData = (RawTypeInfo) factory.getType(LayoutData.class);
        ParameterizedTypeInfo pt_layout2 = (ParameterizedTypeInfo) layoutData.getTypeParameters().get(0).getBaseType();

        assertSame(pt_layout.getRawType(), pt_layout2.getRawType());

        assertEquals("Layout<L>", layout.toString());
        assertEquals("Layout<L=L>", pt_layout.toString());
        assertEquals("LayoutData<L>", layoutData.toString());
        assertEquals("Layout<L=L>", pt_layout2.toString());
    }

    @Test
    public void recursiveMethod() throws Exception {
        MethodInfo method = (MethodInfo) factory.getGenericDeclaration(TypeInfoFactoryTests.class.getDeclaredMethod(
                "testMethod", List.class));

        // Type Vars
        TypeVariableInfo varA = method.getTypeParameters().get(0);
        TypeVariableInfo varB = method.getTypeParameters().get(1);

        // 返回值类型
        TypeVariableInfo returnType = (TypeVariableInfo) method.getReturnType();

        assertEquals(varB, returnType);
        assertSame(method, returnType.getGenericDeclaration());

        // 参数类型
        ParameterizedTypeInfo paramType = (ParameterizedTypeInfo) method.getParameterTypes().get(0);
        TypeVariableInfo paramArgType = (TypeVariableInfo) paramType.getActualTypeArguments().get(0);

        assertEquals(varA, paramArgType);
        assertSame(method, paramArgType.getGenericDeclaration());
    }

    @SuppressWarnings("unused")
    private <A, B extends Number> B testMethod(List<A> list) {
        return null;
    }

    @Test
    public void stressTest() throws Exception {
        File jarFile = new File(getJavaHome(), "jre/lib/rt.jar");

        if (!jarFile.exists()) {
            jarFile = new File(getJavaHome(), "../Classes/classes.jar"); // mac style

            if (!jarFile.exists()) {
                throw new IllegalArgumentException("could not find jar file: jre/lib/rt.jar or classes.jar");
            }
        }

        jarFile = jarFile.getCanonicalFile();
        List<Class<?>> classes = getClasses(jarFile);
        long start = System.currentTimeMillis();

        for (Class<?> c : classes) {
            TypeInfo type = factory.getType(c);

            System.out.println(type);
        }

        long duration = System.currentTimeMillis() - start;
        System.out.println("===========================");
        System.out.printf("Total %,d classes in %,d ms, avg. %,.3f ms.\n", classes.size(), duration, (double) duration
                                                                                                     / classes.size());
    }

    private List<Class<?>> getClasses(File jarFile) throws Exception {
        JarFile jar = new JarFile(jarFile);
        List<Class<?>> classes = new LinkedList<Class<?>>();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        for (Enumeration<JarEntry> i = jar.entries(); i.hasMoreElements(); ) {
            JarEntry entry = i.nextElement();
            String name = entry.getName();

            if (name.endsWith(".class")) {
                name = name.substring(0, name.length() - ".class".length()).replace('/', '.');
                classes.add(Class.forName(name, false, loader));
            }
        }

        jar.close();

        return classes;
    }

    @Test
    public void resolve_includeBaseType() throws Exception {
        ClassTypeInfo myClassType = factory.getClassType(MyClass.class);
        ClassTypeInfo listAType = (ClassTypeInfo) factory.getType(MyClass.class.getField("listA").getGenericType());

        // includeBaseType==false, Iterable<T=E> => Iterable<T=A>
        TypeInfo expectedType = factory.getParameterizedType(Iterable.class, MyClass.class.getTypeParameters()[0]);
        ClassTypeInfo iterableType = (ClassTypeInfo) factory.getType(List.class).getSupertype(Iterable.class);
        TypeInfo resolvedIterableType = iterableType.resolve(listAType, false);

        assertEquals(expectedType, resolvedIterableType);

        // resolvedIterableType应当还能再次resolve:Iterable<T=A> => Iterable<T=Integer>
        expectedType = factory.getParameterizedType(Iterable.class, Integer.class);
        ParameterizedTypeInfo context = factory.getParameterizedType(MyClass.class, Integer.class);

        assertEquals(expectedType, resolvedIterableType.resolve(context));
        assertEquals(expectedType, resolvedIterableType.resolve(context, true));
        assertEquals(expectedType, resolvedIterableType.resolve(context, false));

        // includeBaseType==true, Iterable<T=E> => Iterable<T=Number>
        expectedType = factory.getParameterizedType(Iterable.class, Number.class);

        assertEquals(expectedType, iterableType.resolve(listAType));
        assertEquals(expectedType, iterableType.resolve(listAType, true));

        // includeBaseType==false, T => A
        TypeInfo varA = myClassType.getTypeParameters().get(0);
        TypeInfo varT = iterableType.getTypeParameters().get(0);

        assertEquals(varA, varT.resolve(listAType, false));

        // includeBaseType==true, T => Number
        assertEquals(factory.getType(Number.class), varT.resolve(listAType));
        assertEquals(factory.getType(Number.class), varT.resolve(listAType, true));
    }

    @Test
    public void resolve_includeBaseType_2() throws Exception {
        ClassTypeInfo listAType = (ClassTypeInfo) factory.getType(MyClass2.class.getField("listA").getGenericType());

        // includeBaseType==false, Iterable<T=Collection.E> => Iterable<T=List.E>
        TypeInfo expectedType = factory.getParameterizedType(Iterable.class, List.class.getTypeParameters()[0]);
        ClassTypeInfo iterableType = (ClassTypeInfo) factory.getType(List.class).getSupertype(Iterable.class);
        TypeInfo resolvedIterableType = iterableType.resolve(listAType, false);

        assertEquals(expectedType, resolvedIterableType);

        // resolvedIterableType应当还能再次resolve:Iterable<T=List.E> => Iterable<T=Integer>
        expectedType = factory.getParameterizedType(Iterable.class, Integer.class);
        ParameterizedTypeInfo context = factory.getParameterizedType(List.class, Integer.class);

        assertEquals(expectedType, resolvedIterableType.resolve(context));
        assertEquals(expectedType, resolvedIterableType.resolve(context, true));
        assertEquals(expectedType, resolvedIterableType.resolve(context, false));

        // includeBaseType==true, Iterable<T=E> => Iterable<T=Object>
        expectedType = factory.getParameterizedType(Iterable.class, Object.class);

        assertEquals(expectedType, iterableType.resolve(listAType));
        assertEquals(expectedType, iterableType.resolve(listAType, true));

        // includeBaseType==false, T => List.E
        expectedType = factory.getType(List.class.getTypeParameters()[0]);
        TypeInfo varT = iterableType.getTypeParameters().get(0);

        assertEquals(expectedType, varT.resolve(listAType, false));

        // includeBaseType==true, T => Object
        assertEquals(TypeInfo.OBJECT, varT.resolve(listAType));
        assertEquals(TypeInfo.OBJECT, varT.resolve(listAType, true));
    }
}

class MyClass<A extends Number> {
    public List<A> listA;
}

class MyClass2<A extends Number> {
    @SuppressWarnings("rawtypes")
    public List listA;
}

class Layout<L extends Layout<L>> {
    public LayoutData<L> data;
}

class LayoutData<L extends Layout<L>> {
}
TOP

Related Classes of com.alibaba.citrus.generictype.MyClass2

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.