// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.util;
import jodd.util.fixtures.subclass.IBase;
import jodd.util.fixtures.subclass.IExtra;
import jodd.util.fixtures.subclass.IOne;
import jodd.util.fixtures.subclass.ITwo;
import jodd.util.fixtures.subclass.SBase;
import jodd.util.fixtures.subclass.SOne;
import jodd.util.fixtures.subclass.STwo;
import jodd.util.fixtures.testdata.A;
import jodd.util.fixtures.testdata.B;
import jodd.util.fixtures.testdata.C;
import jodd.util.fixtures.testdata.JavaBean;
import jodd.util.fixtures.testdata2.D;
import jodd.util.fixtures.testdata2.E;
import org.junit.Test;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.*;
public class ClassUtilTest {
@Test
public void testMethod0() {
TFooBean bean = new TFooBean();
Method m;
m = ClassUtil.getMethod0(TFooBean.class, "getMore", String.class, Integer.class);
assertNotNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getMore", String.class, Integer.class);
assertNotNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getXXX", String.class, Integer.class);
assertNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getPublic");
assertNotNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getDefault");
assertNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getProtected");
assertNull(m);
m = ClassUtil.getMethod0(bean.getClass(), "getPrivate");
assertNull(m);
}
@Test
public void testMethod() {
TFooBean bean = new TFooBean();
Method m;
m = ClassUtil.findMethod(TFooBean.class, "getMore");
assertNotNull(m);
m = ClassUtil.findMethod(bean.getClass(), "getMore");
assertNotNull(m);
m = ClassUtil.findMethod(bean.getClass(), "getXXX");
assertNull(m);
}
@Test
public void testMatchClasses() {
TFooBean a = new TFooBean();
TFooBean b = new TFooBean();
TFooBean2 c = new TFooBean2();
assertTrue(TFooBean.class.isInstance(a));
assertTrue(ClassUtil.isTypeOf(TFooBean.class, a.getClass()));
assertTrue(ClassUtil.isTypeOf(TFooBean.class, b.getClass()));
assertTrue(ClassUtil.isTypeOf(a.getClass(), b.getClass()));
assertTrue(ClassUtil.isTypeOf(b.getClass(), a.getClass()));
assertTrue(ClassUtil.isTypeOf(TFooBean2.class, c.getClass()));
assertTrue(ClassUtil.isTypeOf(TFooBean2.class, TFooBean.class));
assertFalse(ClassUtil.isTypeOf(TFooBean.class, TFooBean2.class));
assertTrue(ClassUtil.isTypeOf(c.getClass(), TFooBean.class));
assertFalse(ClassUtil.isTypeOf(a.getClass(), TFooBean2.class));
assertTrue(ClassUtil.isTypeOf(TFooBean.class, Serializable.class));
assertTrue(Serializable.class.isInstance(c));
//noinspection ConstantConditions
assertTrue(c instanceof Serializable);
assertTrue(ClassUtil.isInstanceOf(c, Serializable.class));
assertTrue(ClassUtil.isTypeOf(TFooBean2.class, Serializable.class));
assertTrue(ClassUtil.isTypeOf(TFooBean2.class, Comparable.class));
assertFalse(ClassUtil.isTypeOf(TFooBean.class, Comparable.class));
assertTrue(ClassUtil.isTypeOf(TFooBean.class, TFooIndyEx.class));
assertTrue(ClassUtil.isTypeOf(TFooBean2.class, TFooIndyEx.class));
assertTrue(ClassUtil.isTypeOf(TFooBean.class, TFooIndy.class));
}
@Test
public void testMatchInterfaces() {
assertTrue(ClassUtil.isTypeOf(HashMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(AbstractMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(Map.class, Map.class));
assertTrue(ClassUtil.isInstanceOf(new HashMap(), Map.class));
assertTrue(ClassUtil.isTypeOf(HashMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(AbstractMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(HashMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(Map.class, Map.class));
assertTrue(ClassUtil.isTypeOf(HashMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(AbstractMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(HashMap.class, Map.class));
assertTrue(ClassUtil.isTypeOf(Map.class, Map.class));
}
@Test
public void testAccessibleA() {
Method[] ms = ClassUtil.getAccessibleMethods(A.class, null);
assertEquals(4 + 11, ms.length); // there are 11 accessible Object methods (9 public + 2 protected)
ms = ClassUtil.getAccessibleMethods(A.class);
assertEquals(4, ms.length);
ms = A.class.getMethods();
assertEquals(1 + 9, ms.length); // there are 9 public Object methods
ms = A.class.getDeclaredMethods();
assertEquals(4, ms.length);
ms = ClassUtil.getSupportedMethods(A.class, null);
assertEquals(4 + 12, ms.length); // there are 12 total Object methods (9 public + 2 protected + 1 private)
ms = ClassUtil.getSupportedMethods(A.class);
assertEquals(4, ms.length);
Field[] fs = ClassUtil.getAccessibleFields(A.class);
assertEquals(4, fs.length);
fs = A.class.getFields();
assertEquals(1, fs.length);
fs = A.class.getDeclaredFields();
assertEquals(4, fs.length);
fs = ClassUtil.getSupportedFields(A.class);
assertEquals(4, fs.length);
}
@Test
public void testAccessibleB() {
Method[] ms = ClassUtil.getAccessibleMethods(B.class, null);
assertEquals(3 + 11, ms.length);
ms = ClassUtil.getAccessibleMethods(B.class);
assertEquals(3, ms.length);
ms = B.class.getMethods();
assertEquals(1 + 9, ms.length);
ms = B.class.getDeclaredMethods();
assertEquals(0, ms.length);
ms = ClassUtil.getSupportedMethods(B.class, null);
assertEquals(4 + 12, ms.length);
ms = ClassUtil.getSupportedMethods(B.class);
assertEquals(4, ms.length);
Field[] fs = ClassUtil.getAccessibleFields(B.class);
assertEquals(3, fs.length);
fs = B.class.getFields();
assertEquals(1, fs.length);
fs = B.class.getDeclaredFields();
assertEquals(0, fs.length);
fs = ClassUtil.getSupportedFields(B.class);
assertEquals(4, fs.length);
}
@Test
public void testAccessibleC() {
Method[] ms = ClassUtil.getAccessibleMethods(C.class, null);
assertEquals(5 + 11, ms.length);
ms = ClassUtil.getAccessibleMethods(C.class);
assertEquals(5, ms.length);
ms = C.class.getMethods();
assertEquals(2 + 9, ms.length);
ms = C.class.getDeclaredMethods();
assertEquals(5, ms.length);
ms = ClassUtil.getSupportedMethods(C.class, null);
assertEquals(5 + 12, ms.length);
ms = ClassUtil.getSupportedMethods(C.class);
assertEquals(5, ms.length);
Field[] fs = ClassUtil.getAccessibleFields(C.class);
assertEquals(5, fs.length);
fs = C.class.getFields();
assertEquals(3, fs.length);
fs = C.class.getDeclaredFields();
assertEquals(5, fs.length);
fs = ClassUtil.getSupportedFields(C.class);
assertEquals(5, fs.length);
}
@Test
public void testAccessibleD() {
Method[] ms = ClassUtil.getAccessibleMethods(D.class, null);
assertEquals(3 + 11, ms.length);
ms = ClassUtil.getAccessibleMethods(D.class);
assertEquals(3, ms.length);
ms = D.class.getMethods();
assertEquals(2 + 9, ms.length);
ms = D.class.getDeclaredMethods();
assertEquals(0, ms.length);
ms = ClassUtil.getSupportedMethods(D.class, null);
assertEquals(5 + 12, ms.length);
ms = ClassUtil.getSupportedMethods(D.class);
assertEquals(5, ms.length);
Field[] fs = ClassUtil.getAccessibleFields(D.class);
assertEquals(3, fs.length);
fs = D.class.getFields();
assertEquals(3, fs.length);
fs = D.class.getDeclaredFields();
assertEquals(0, fs.length);
fs = ClassUtil.getSupportedFields(D.class);
assertEquals(5, fs.length);
}
@Test
public void testAccessibleE() {
Method[] ms = ClassUtil.getAccessibleMethods(E.class, null);
assertEquals(5 + 11, ms.length);
ms = ClassUtil.getAccessibleMethods(E.class);
assertEquals(5, ms.length);
ms = E.class.getMethods();
assertEquals(2 + 9, ms.length);
ms = E.class.getDeclaredMethods();
assertEquals(4, ms.length);
ms = ClassUtil.getSupportedMethods(E.class, null);
assertEquals(5 + 12, ms.length);
ms = ClassUtil.getSupportedMethods(E.class);
assertEquals(5, ms.length);
Field[] fs = ClassUtil.getAccessibleFields(E.class);
assertEquals(5, fs.length);
fs = E.class.getFields();
assertEquals(4, fs.length);
fs = E.class.getDeclaredFields();
assertEquals(4, fs.length);
fs = ClassUtil.getSupportedFields(E.class);
assertEquals(5, fs.length);
}
@Test
public void testIsSubclassAndInterface() {
assertTrue(ClassUtil.isTypeOf(SBase.class, SBase.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, SBase.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, IOne.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, IOne.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, Serializable.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, Serializable.class));
assertTrue(ClassUtil.isTypeOf(SOne.class, SOne.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, SBase.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IOne.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IOne.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, Serializable.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, Serializable.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, ITwo.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, ITwo.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IBase.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IBase.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IExtra.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, IExtra.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, STwo.class));
assertTrue(ClassUtil.isTypeOf(STwo.class, STwo.class));
}
@Test
public void testBeanPropertyNames() {
String name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getOne"));
assertEquals("one", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setOne"));
assertEquals("one", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "isTwo"));
assertEquals("two", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setTwo"));
assertEquals("two", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getThree"));
assertEquals("three", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setThree"));
assertEquals("three", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getF"));
assertEquals("f", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setF"));
assertEquals("f", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getG"));
assertEquals("g", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setG"));
assertEquals("g", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getURL"));
assertEquals("URL", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setURL"));
assertEquals("URL", name);
name = ClassUtil.getBeanPropertyGetterName(ClassUtil.findMethod(JavaBean.class, "getBIGsmall"));
assertEquals("BIGsmall", name);
name = ClassUtil.getBeanPropertySetterName(ClassUtil.findMethod(JavaBean.class, "setBIGsmall"));
assertEquals("BIGsmall", name);
}
@Test
public void testIsSubClassForCommonTypes() {
assertTrue(ClassUtil.isTypeOf(Long.class, Long.class));
assertFalse(ClassUtil.isTypeOf(Long.class, long.class));
}
/* @Test
public void testGetCallerClass() {
assertFalse(Reflection.getCallerClass(0).equals(ReflectUtil.getCallerClass(0)));
assertEquals(Reflection.getCallerClass(1), ReflectUtil.getCallerClass(1));
assertEquals(Reflection.getCallerClass(2), ReflectUtil.getCallerClass(2));
assertEquals(Reflection.getCallerClass(3), ReflectUtil.getCallerClass(3));
assertEquals(ReflectUtilTest.class, ReflectUtil.getCallerClass(1));
}
@Test
public void testGetCallerClass2() throws NoSuchFieldException, IllegalAccessException {
Field field = ReflectUtil.class.getDeclaredField("SECURITY_MANAGER");
field.setAccessible(true);
Object value = field.get(null);
field.set(null, null);
assertFalse(Reflection.getCallerClass(0).equals(ReflectUtil.getCallerClass(0)));
assertEquals(Reflection.getCallerClass(1), ReflectUtil.getCallerClass(1));
assertEquals(Reflection.getCallerClass(2), ReflectUtil.getCallerClass(2));
assertEquals(Reflection.getCallerClass(3), ReflectUtil.getCallerClass(3));
assertEquals(ReflectUtilTest.class, ReflectUtil.getCallerClass(1));
field.set(null, value);
}
*/
// ---------------------------------------------------------------- field concrete type
public static class BaseClass<A, B> {
public A f1;
public B f2;
public String f3;
public A[] array1;
}
public static class ConcreteClass extends BaseClass<String, Integer> {
public Long f4;
public List<Long> f5;
}
public static class BaseClass2<X> extends BaseClass<X, Integer> {
}
public static class ConcreteClass2 extends BaseClass2<String> {
}
@Test
public void testGetFieldConcreteType() throws NoSuchFieldException {
Field f1 = BaseClass.class.getField("f1");
Field f2 = BaseClass.class.getField("f2");
Field f3 = BaseClass.class.getField("f3");
Field f4 = ConcreteClass.class.getField("f4");
Field f5 = ConcreteClass.class.getField("f5");
Field array1 = BaseClass.class.getField("array1");
Class[] genericSupertypes = ClassUtil.getGenericSupertypes(ConcreteClass.class);
assertEquals(String.class, genericSupertypes[0]);
assertEquals(Integer.class, genericSupertypes[1]);
assertEquals(String.class, ClassUtil.getRawType(f1.getGenericType(), ConcreteClass.class));
assertEquals(Integer.class, ClassUtil.getRawType(f2.getGenericType(), ConcreteClass.class));
assertEquals(String.class, ClassUtil.getRawType(f3.getGenericType(), ConcreteClass.class));
assertEquals(Long.class, ClassUtil.getRawType(f4.getGenericType(), ConcreteClass.class));
assertEquals(List.class, ClassUtil.getRawType(f5.getGenericType(), ConcreteClass.class));
assertEquals(String[].class, ClassUtil.getRawType(array1.getGenericType(), ConcreteClass.class));
assertEquals(Object.class, ClassUtil.getRawType(f1.getGenericType()));
assertNull(ClassUtil.getComponentType(f1.getGenericType(), -1));
assertEquals(Long.class, ClassUtil.getComponentType(f5.getGenericType(), 0));
}
@Test
public void testGetFieldConcreteType2() throws Exception {
Field array1 = BaseClass.class.getField("array1");
Field f2 = ConcreteClass2.class.getField("f2");
assertEquals(String[].class, ClassUtil.getRawType(array1.getGenericType(), ConcreteClass2.class));
assertEquals(Integer.class, ClassUtil.getRawType(f2.getGenericType(), ConcreteClass2.class));
assertEquals(Integer.class, ClassUtil.getRawType(f2.getGenericType(), BaseClass2.class));
}
// ---------------------------------------------------------------- test raw
public static class Soo {
public List<String> stringList;
public String[] strings;
public String string;
public List<Integer> getIntegerList() {return null;}
public Integer[] getIntegers() {return null;}
public Integer getInteger() {return null;}
public <T> T getTemplate(T foo) {return null;}
public Collection<? extends Number> getCollection() {return null;}
public Collection<?> getCollection2() {return null;}
}
@Test
public void testGetRawAndComponentType() throws NoSuchFieldException {
Class<Soo> sooClass = Soo.class;
Field stringList = sooClass.getField("stringList");
assertEquals(List.class, ClassUtil.getRawType(stringList.getType()));
assertEquals(String.class, ClassUtil.getComponentType(stringList.getGenericType(), 0));
Field strings = sooClass.getField("strings");
assertEquals(String[].class, ClassUtil.getRawType(strings.getType()));
assertEquals(String.class, ClassUtil.getComponentType(strings.getGenericType(), -1));
Field string = sooClass.getField("string");
assertEquals(String.class, ClassUtil.getRawType(string.getType()));
assertNull(ClassUtil.getComponentType(string.getGenericType(), 0));
Method integerList = ClassUtil.findMethod(sooClass, "getIntegerList");
assertEquals(List.class, ClassUtil.getRawType(integerList.getReturnType()));
assertEquals(Integer.class, ClassUtil.getComponentType(integerList.getGenericReturnType(), -1));
Method integers = ClassUtil.findMethod(sooClass, "getIntegers");
assertEquals(Integer[].class, ClassUtil.getRawType(integers.getReturnType()));
assertEquals(Integer.class, ClassUtil.getComponentType(integers.getGenericReturnType(), 0));
Method integer = ClassUtil.findMethod(sooClass, "getInteger");
assertEquals(Integer.class, ClassUtil.getRawType(integer.getReturnType()));
assertNull(ClassUtil.getComponentType(integer.getGenericReturnType(), -1));
Method template = ClassUtil.findMethod(sooClass, "getTemplate");
assertEquals(Object.class, ClassUtil.getRawType(template.getReturnType()));
assertNull(ClassUtil.getComponentType(template.getGenericReturnType(), 0));
Method collection = ClassUtil.findMethod(sooClass, "getCollection");
assertEquals(Collection.class, ClassUtil.getRawType(collection.getReturnType()));
assertEquals(Number.class, ClassUtil.getComponentType(collection.getGenericReturnType(), -1));
Method collection2 = ClassUtil.findMethod(sooClass, "getCollection2");
assertEquals(Collection.class, ClassUtil.getRawType(collection2.getReturnType()));
assertEquals(Object.class, ClassUtil.getComponentType(collection2.getGenericReturnType(), 0));
}
public static class Base2<N extends Number, K> {
public N getNumber() {return null;}
public K getKiko() {return null;}
}
public static class Impl1<N extends Number> extends Base2<N, Long> {}
public static class Impl2 extends Impl1<Integer> {}
public static class Impl3 extends Impl2 {}
@Test
public void testGetRawWithImplClass() throws NoSuchFieldException {
Method number = ClassUtil.findMethod(Base2.class, "getNumber");
Method kiko = ClassUtil.findMethod(Base2.class, "getKiko");
assertEquals(Number.class, ClassUtil.getRawType(number.getReturnType()));
assertEquals(Number.class, ClassUtil.getRawType(number.getGenericReturnType()));
assertEquals(Object.class, ClassUtil.getRawType(kiko.getReturnType()));
assertEquals(Object.class, ClassUtil.getRawType(kiko.getGenericReturnType()));
assertEquals(Number.class, ClassUtil.getRawType(number.getReturnType(), Impl1.class));
assertEquals(Number.class, ClassUtil.getRawType(number.getGenericReturnType(), Impl1.class));
assertEquals(Object.class, ClassUtil.getRawType(kiko.getReturnType(), Impl1.class));
assertEquals(Long.class, ClassUtil.getRawType(kiko.getGenericReturnType(), Impl1.class));
assertEquals(Number.class, ClassUtil.getRawType(number.getReturnType(), Impl2.class));
assertEquals(Integer.class, ClassUtil.getRawType(number.getGenericReturnType(), Impl2.class));
assertEquals(Object.class, ClassUtil.getRawType(kiko.getReturnType(), Impl2.class));
assertEquals(Long.class, ClassUtil.getRawType(kiko.getGenericReturnType(), Impl2.class));
assertEquals(Number.class, ClassUtil.getRawType(number.getReturnType(), Impl3.class));
assertEquals(Integer.class, ClassUtil.getRawType(number.getGenericReturnType(), Impl3.class));
assertEquals(Object.class, ClassUtil.getRawType(kiko.getReturnType(), Impl3.class));
assertEquals(Long.class, ClassUtil.getRawType(kiko.getGenericReturnType(), Impl3.class));
}
public static class Base22<K, N extends Number> {}
public static class Impl11<N extends Number> extends Base22<Long, N> {}
public static class Impl22 extends Impl11<Integer> {}
public static class Impl33 extends Impl22 {}
@Test
public void testClassGenerics1() {
Class[] componentTypes = ClassUtil.getGenericSupertypes(Base2.class);
assertNull(componentTypes);
Type[] types = Base2.class.getGenericInterfaces();
assertEquals(0, types.length);
componentTypes = ClassUtil.getGenericSupertypes(Impl1.class);
assertEquals(2, componentTypes.length);
assertEquals(Number.class, componentTypes[0]);
assertEquals(Long.class, componentTypes[1]);
types = Impl1.class.getGenericInterfaces();
assertEquals(0, types.length);
componentTypes = ClassUtil.getGenericSupertypes(Impl2.class);
assertEquals(1, componentTypes.length);
assertEquals(Integer.class, componentTypes[0]);
types = Impl2.class.getGenericInterfaces();
assertEquals(0, types.length);
componentTypes = ClassUtil.getGenericSupertypes(Impl3.class);
assertNull(componentTypes);
}
@Test
public void testClassGenerics2() {
Class[] componentTypes = ClassUtil.getGenericSupertypes(Base22.class);
assertNull(componentTypes);
componentTypes = ClassUtil.getGenericSupertypes(Impl11.class);
assertEquals(2, componentTypes.length);
assertEquals(Long.class, componentTypes[0]);
assertEquals(Number.class, componentTypes[1]);
componentTypes = ClassUtil.getGenericSupertypes(Impl22.class);
assertEquals(1, componentTypes.length);
assertEquals(Integer.class, componentTypes[0]);
componentTypes = ClassUtil.getGenericSupertypes(Impl33.class);
assertNull(componentTypes);
}
public static interface BaseAna<K, N extends Number> {}
public static interface ImplAna<N extends Number> extends BaseAna<Long, N> {}
public static interface ImplAna2 extends ImplAna<Integer> {}
public static class ImplAna3 implements ImplAna2 {}
public static class ImplAna4 extends ImplAna3 {}
@Test
public void testClassGenerics3() {
Class[] componentTypes = ClassUtil.getGenericSupertypes(BaseAna.class);
assertNull(componentTypes);
componentTypes = ClassUtil.getGenericSupertypes(ImplAna.class);
assertNull(componentTypes);
componentTypes = ClassUtil.getGenericSupertypes(ImplAna2.class);
assertNull(componentTypes);
componentTypes = ClassUtil.getGenericSupertypes(ImplAna3.class);
assertNull(componentTypes);
// scan generic interfacase
Type[] types = ImplAna3.class.getGenericInterfaces();
assertEquals(1, types.length);
assertEquals(ImplAna2.class, types[0]);
assertNull(ClassUtil.getComponentType(types[0], 0));
types = ImplAna2.class.getGenericInterfaces();
assertEquals(1, types.length);
assertEquals(Integer.class, ClassUtil.getComponentType(types[0], 0));
types = ImplAna.class.getGenericInterfaces();
assertEquals(1, types.length);
assertEquals(Long.class, ClassUtil.getComponentType(types[0], 0));
types = BaseAna.class.getGenericInterfaces();
assertEquals(0, types.length);
types = ImplAna4.class.getGenericInterfaces();
assertEquals(0, types.length);
}
// ---------------------------------------------------------------- type2string
public static class FieldType<K extends Number, V extends List<String> & Collection<String>> {
List fRaw;
List<Object> fTypeObject;
List<String> fTypeString;
List<?> fWildcard;
List<? super List<String>> fBoundedWildcard;
Map<String, List<Set<Long>>> fTypeNested;
Map<K, V> fTypeLiteral;
K[] fGenericArray;
}
@Test
public void testFieldTypeToString() {
Field[] fields = FieldType.class.getDeclaredFields();
Arrays.sort(fields, new Comparator<Field>() {
public int compare(Field o1, Field o2) {
return o1.getName().compareTo(o2.getName());
}
});
String result = "";
for (Field field : fields) {
Type type = field.getGenericType();
result += field.getName() + " - " + ClassUtil.typeToString(type) + '\n';
}
assertEquals(
"fBoundedWildcard - java.util.List<? super java.util.List<java.lang.String>>\n" +
"fGenericArray - K[]\n" +
"fRaw - java.util.List\n" +
"fTypeLiteral - java.util.Map<K extends java.lang.Number>, <V extends java.util.List<java.lang.String> & java.util.Collection<java.lang.String>>\n" +
"fTypeNested - java.util.Map<java.lang.String>, <java.util.List<java.util.Set<java.lang.Long>>>\n" +
"fTypeObject - java.util.List<java.lang.Object>\n" +
"fTypeString - java.util.List<java.lang.String>\n" +
"fWildcard - java.util.List<? extends java.lang.Object>\n",
result);
}
public static class MethodReturnType {
List mRaw() {return null;}
List<String> mTypeString() {return null;}
List<?> mWildcard() {return null;}
List<? extends Number> mBoundedWildcard() {return null;}
<T extends List<String>> List<T> mTypeLiteral() {return null;}
}
@Test
public void testMethodTypeToString() {
Method[] methods = MethodReturnType.class.getDeclaredMethods();
Arrays.sort(methods, new Comparator<Method>() {
public int compare(Method o1, Method o2) {
return o1.getName().compareTo(o2.getName());
}
});
String result = "";
for (Method method : methods) {
Type type = method.getGenericReturnType();
result += method.getName() + " - " + ClassUtil.typeToString(type) + '\n';
}
assertEquals(
"mBoundedWildcard - java.util.List<? extends java.lang.Number>\n" +
"mRaw - java.util.List\n" +
"mTypeLiteral - java.util.List<T extends java.util.List<java.lang.String>>\n" +
"mTypeString - java.util.List<java.lang.String>\n" +
"mWildcard - java.util.List<? extends java.lang.Object>\n",
result);
}
public static class MethodParameterType<A> {
<T extends List<T>> void m(A a, String p1, T p2, List<?> p3, List<T> p4) { }
}
public static class Mimple extends MethodParameterType<Long>{}
@Test
public void testMethodParameterTypeToString() {
String result = "";
Method method = null;
for (Method m : MethodParameterType.class.getDeclaredMethods()) {
for (Type type : m.getGenericParameterTypes()) {
result += m.getName() + " - " + ClassUtil.typeToString(type) + '\n';
}
method = m;
}
assertEquals(
"m - A extends java.lang.Object\n" +
"m - java.lang.String\n" +
"m - T extends java.util.List<T>\n" +
"m - java.util.List<? extends java.lang.Object>\n" +
"m - java.util.List<T extends java.util.List<T>>\n",
result);
Type[] types = method.getGenericParameterTypes();
assertEquals(Object.class, ClassUtil.getRawType(types[0], MethodParameterType.class));
assertEquals(String.class, ClassUtil.getRawType(types[1], MethodParameterType.class));
assertEquals(List.class, ClassUtil.getRawType(types[2], MethodParameterType.class));
assertEquals(List.class, ClassUtil.getRawType(types[3], MethodParameterType.class));
assertEquals(List.class, ClassUtil.getRawType(types[4], MethodParameterType.class));
// same methods, using different impl class
assertEquals(Long.class, ClassUtil.getRawType(types[0], Mimple.class)); // change!
assertEquals(String.class, ClassUtil.getRawType(types[1], Mimple.class));
assertEquals(List.class, ClassUtil.getRawType(types[2], Mimple.class));
assertEquals(List.class, ClassUtil.getRawType(types[3], Mimple.class));
assertEquals(List.class, ClassUtil.getRawType(types[4], Mimple.class));
}
public interface SomeGuy {}
public interface Cool extends SomeGuy {}
public interface Vigilante {}
public interface Flying extends Vigilante {}
public interface SuperMario extends Flying, Cool {}
public class User implements SomeGuy {}
public class SuperUser extends User implements Cool {}
public class SuperMan extends SuperUser implements Flying {}
@Test
public void testResolveAllInterfaces() {
Class[] interfaces = ClassUtil.resolveAllInterfaces(HashMap.class);
assertTrue(interfaces.length >= 3);
assertTrue(ArraysUtil.contains(interfaces, Map.class));
assertTrue(ArraysUtil.contains(interfaces, Serializable.class));
assertTrue(ArraysUtil.contains(interfaces, Cloneable.class));
interfaces = ClassUtil.resolveAllInterfaces(SuperMan.class);
assertEquals(4, interfaces.length);
assertTrue(ArraysUtil.contains(interfaces, SomeGuy.class));
assertTrue(ArraysUtil.contains(interfaces, Cool.class));
assertTrue(ArraysUtil.contains(interfaces, Flying.class));
assertTrue(ArraysUtil.contains(interfaces, Vigilante.class));
assertTrue(ArraysUtil.indexOf(interfaces, Flying.class) < ArraysUtil.indexOf(interfaces, SomeGuy.class));
interfaces = ClassUtil.resolveAllInterfaces(SuperUser.class);
assertEquals(2, interfaces.length);
assertTrue(ArraysUtil.contains(interfaces, SomeGuy.class));
assertTrue(ArraysUtil.contains(interfaces, Cool.class));
interfaces = ClassUtil.resolveAllInterfaces(User.class);
assertEquals(1, interfaces.length);
assertTrue(ArraysUtil.contains(interfaces, SomeGuy.class));
interfaces = ClassUtil.resolveAllInterfaces(SomeGuy.class);
assertEquals(0, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(Cool.class);
assertEquals(1, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(Vigilante.class);
assertEquals(0, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(Flying.class);
assertEquals(1, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(SuperMario.class);
assertEquals(4, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(Object.class);
assertEquals(0, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(int.class);
assertEquals(0, interfaces.length);
interfaces = ClassUtil.resolveAllInterfaces(int[].class);
assertEquals(2, interfaces.length); // cloneable, serializable
interfaces = ClassUtil.resolveAllInterfaces(Integer[].class);
assertEquals(2, interfaces.length);
}
@Test
public void testResolveAllSuperclsses() {
Class[] subclasses = ClassUtil.resolveAllSuperclasses(User.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(SuperUser.class);
assertEquals(1, subclasses.length);
assertEquals(User.class, subclasses[0]);
subclasses = ClassUtil.resolveAllSuperclasses(SuperMan.class);
assertEquals(2, subclasses.length);
assertEquals(SuperUser.class, subclasses[0]);
assertEquals(User.class, subclasses[1]);
subclasses = ClassUtil.resolveAllSuperclasses(Cool.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(Flying.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(SuperMario.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(Object.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(int.class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(int[].class);
assertEquals(0, subclasses.length);
subclasses = ClassUtil.resolveAllSuperclasses(Integer[].class);
assertEquals(0, subclasses.length);
}
}