/*
* 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.util.ArrayUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import com.alibaba.citrus.generictype.impl.TypeInfoFactory;
/**
* 测试类的基类。
*
* @author Michael Zhou
*/
public abstract class BaseTypeTests {
protected static Type getReturnType(Class<?> ownerType, String methodName) {
try {
return ownerType.getDeclaredMethod(methodName).getGenericReturnType();
} catch (Exception e) {
fail(e.toString());
return null;
}
}
protected static Type getArgOfReturnType(Class<?> ownerType, String methodName) {
return ((ParameterizedType) getReturnType(ownerType, methodName)).getActualTypeArguments()[0];
}
/** 取得指定名称的method或指定参数个数的constructor。 */
protected static GenericDeclaration getMethodOrConstructor(Class<?> ownerType, String methodName,
Class<?>[] paramTypes) throws NoSuchMethodException {
if (methodName != null) {
try {
return ownerType.getMethod(methodName, paramTypes);
} catch (NoSuchMethodException e) {
return ownerType.getDeclaredMethod(methodName, paramTypes);
}
} else {
return ownerType.getDeclaredConstructor(paramTypes);
}
}
protected static void assertSupertypes(TypeInfo type, String... expectedSupertypes) {
List<TypeInfo> supertypes = createArrayList(type.getSupertypes());
List<TypeInfo> superclasses = createArrayList(type.getSuperclasses());
List<TypeInfo> interfaces = createArrayList(type.getInterfaces());
// 先判断顺序:本身、类、接口、Object
assertThat(supertypes.size(), greaterThan(0));
// 第一个是自己
TypeInfo first = findNonBoundedType(type);
if (first.getComponentType() instanceof BoundedTypeInfo) {
assertEquals(findNonBoundedType(first.getComponentType()), supertypes.get(0).getComponentType());
} else {
assertEquals(first, supertypes.get(0));
}
boolean isInterface = type.getRawType().isInterface();
if (!isInterface && !type.getRawType().isPrimitive()) {
assertEquals(Object.class, supertypes.get(supertypes.size() - 1).getRawType()); // 最后一个是Object
}
// 排序
Comparator<TypeInfo> comparator = new Comparator<TypeInfo>() {
public int compare(TypeInfo o1, TypeInfo o2) {
int c1 = o1.getRawType().isInterface() ? 1 : o1.getRawType().equals(Object.class) ? 2 : 0;
int c2 = o2.getRawType().isInterface() ? 1 : o2.getRawType().equals(Object.class) ? 2 : 0;
if (c1 != c2) {
return c1 - c2; // 按class, interface, Object排序
} else if (c1 == 0) {
return 0; // class不排序
} else {
return o1.toString().compareTo(o2.toString()); // interface按名称排序
}
}
};
Collections.sort(supertypes.subList(1, supertypes.size()), comparator);
if (type.isInterface()) {
Collections.sort(superclasses, comparator);
Collections.sort(interfaces.subList(1, interfaces.size()), comparator);
} else {
Collections.sort(superclasses.subList(1, superclasses.size()), comparator);
Collections.sort(interfaces, comparator);
}
if (isEmptyArray(expectedSupertypes)) {
StringBuilder buf = new StringBuilder("\n");
for (Iterator<TypeInfo> i = supertypes.iterator(); i.hasNext(); ) {
buf.append("\"").append(i.next()).append("\"");
if (i.hasNext()) {
buf.append(", ");
}
}
fail(buf.toString());
}
Iterator<TypeInfo> i = supertypes.iterator();
Iterator<TypeInfo> itfs = interfaces.iterator();
Iterator<TypeInfo> classes = superclasses.iterator();
for (String expectedSupertype : expectedSupertypes) {
TypeInfo supertype = i.next();
assertEquals(expectedSupertype, supertype.toString());
if (supertype.getRawType().isInterface()) {
assertEquals(itfs.next(), supertype);
} else {
assertEquals(classes.next(), supertype);
}
assertTrue(String.format("%s is not assignable from %s", supertype, type), supertype.getRawType()
.isAssignableFrom(type.getRawType()));
// 测试getSupertype()
assertSame(supertype, type.getSupertype(supertype.getRawType()));
}
assertFalse("getSupertypes still has elements", i.hasNext());
assertFalse("getInterfaces still has elements", itfs.hasNext());
assertFalse("getSuperclasses still has elements", classes.hasNext());
}
// 调用TypeInfoFactory.findNonBoundedType
protected static TypeInfo findNonBoundedType(TypeInfo type) {
Method m;
try {
m = TypeInfoFactory.class.getDeclaredMethod("findNonBoundedType", TypeInfo.class);
m.setAccessible(true);
return (TypeInfo) m.invoke(null, type);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}