package com.fasterxml.jackson.databind.type; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import com.fasterxml.jackson.databind.BaseMapTest; import com.fasterxml.jackson.databind.JavaType; /** * Simple tests to verify that {@link JavaType} types work to * some degree */ public class TestJavaType extends BaseMapTest { static class BaseType { } static class SubType extends BaseType { } static enum MyEnum { A, B; } static enum MyEnum2 { A(1), B(2); private MyEnum2(int value) { } } static enum MyEnumSub { A(1) { @Override public String toString() { return "a"; } }, B(2) { @Override public String toString() { return "b"; } } ; private MyEnumSub(int value) { } } // [databind#728] static class Issue728 { public C method(C input) { return null; } } public interface Generic1194 { public AtomicReference getGeneric(); public List getList(); public Map getMap(); } @SuppressWarnings("serial") static class AtomicStringReference extends AtomicReference { } /* /********************************************************** /* Test methods /********************************************************** */ public void testLocalType728() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); Method m = Issue728.class.getMethod("method", CharSequence.class); assertNotNull(m); // Start with return type // first type-erased JavaType t = tf.constructType(m.getReturnType()); assertEquals(CharSequence.class, t.getRawClass()); // then generic t = tf.constructType(m.getGenericReturnType()); assertEquals(CharSequence.class, t.getRawClass()); // then parameter type t = tf.constructType(m.getParameterTypes()[0]); assertEquals(CharSequence.class, t.getRawClass()); t = tf.constructType(m.getGenericParameterTypes()[0]); assertEquals(CharSequence.class, t.getRawClass()); } public void testSimpleClass() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType baseType = tf.constructType(BaseType.class); assertSame(BaseType.class, baseType.getRawClass()); assertTrue(baseType.hasRawClass(BaseType.class)); assertFalse(baseType.isTypeOrSubTypeOf(SubType.class)); assertFalse(baseType.isArrayType()); assertFalse(baseType.isContainerType()); assertFalse(baseType.isEnumType()); assertFalse(baseType.isInterface()); assertFalse(baseType.isPrimitive()); assertFalse(baseType.isReferenceType()); assertFalse(baseType.hasContentType()); assertNull(baseType.getContentType()); assertNull(baseType.getKeyType()); assertNull(baseType.getValueHandler()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$BaseType;", baseType.getGenericSignature()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$BaseType;", baseType.getErasedSignature()); } @SuppressWarnings("deprecation") public void testDeprecated() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType baseType = tf.constructType(BaseType.class); assertTrue(baseType.hasRawClass(BaseType.class)); assertNull(baseType.getParameterSource()); assertNull(baseType.getContentTypeHandler()); assertNull(baseType.getContentValueHandler()); assertFalse(baseType.hasValueHandler()); assertFalse(baseType.hasHandlers()); assertSame(baseType, baseType.forcedNarrowBy(BaseType.class)); JavaType sub = baseType.forcedNarrowBy(SubType.class); assertTrue(sub.hasRawClass(SubType.class)); } public void testArrayType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType arrayT = ArrayType.construct(tf.constructType(String.class), null); assertNotNull(arrayT); assertTrue(arrayT.isContainerType()); assertFalse(arrayT.isReferenceType()); assertTrue(arrayT.hasContentType()); assertNotNull(arrayT.toString()); assertNotNull(arrayT.getContentType()); assertNull(arrayT.getKeyType()); assertTrue(arrayT.equals(arrayT)); assertFalse(arrayT.equals(null)); final Object bogus = "xyz"; assertFalse(arrayT.equals(bogus)); assertTrue(arrayT.equals(ArrayType.construct(tf.constructType(String.class), null))); assertFalse(arrayT.equals(ArrayType.construct(tf.constructType(Integer.class), null))); } public void testMapType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType mapT = tf.constructType(HashMap.class); assertTrue(mapT.isContainerType()); assertFalse(mapT.isReferenceType()); assertTrue(mapT.hasContentType()); assertNotNull(mapT.toString()); assertNotNull(mapT.getContentType()); assertNotNull(mapT.getKeyType()); assertEquals("Ljava/util/HashMap;", mapT.getGenericSignature()); assertEquals("Ljava/util/HashMap;", mapT.getErasedSignature()); assertTrue(mapT.equals(mapT)); assertFalse(mapT.equals(null)); Object bogus = "xyz"; assertFalse(mapT.equals(bogus)); } public void testEnumType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType enumT = tf.constructType(MyEnum.class); // JDK actually works fine with "basic" Enum types... assertTrue(enumT.getRawClass().isEnum()); assertTrue(enumT.isEnumType()); assertTrue(enumT.isEnumImplType()); assertFalse(enumT.hasHandlers()); assertTrue(enumT.isTypeOrSubTypeOf(MyEnum.class)); assertTrue(enumT.isTypeOrSubTypeOf(Object.class)); assertNull(enumT.containedType(3)); assertTrue(enumT.containedTypeOrUnknown(3).isJavaLangObject()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$MyEnum;", enumT.getGenericSignature()); assertEquals("Lcom/fasterxml/jackson/databind/type/TestJavaType$MyEnum;", enumT.getErasedSignature()); assertTrue(tf.constructType(MyEnum2.class).isEnumType()); assertTrue(tf.constructType(MyEnum.A.getClass()).isEnumType()); assertTrue(tf.constructType(MyEnum2.A.getClass()).isEnumType()); // [databind#2480] assertFalse(tf.constructType(Enum.class).isEnumImplType()); JavaType enumSubT = tf.constructType(MyEnumSub.B.getClass()); assertTrue(enumSubT.isEnumType()); assertTrue(enumSubT.isEnumImplType()); // and this is kind of odd twist by JDK: one might except this to return true, // but no, sub-classes (when Enum values have overrides, and require sub-class) // are NOT considered enums for whatever reason assertFalse(enumSubT.getRawClass().isEnum()); } public void testClassKey() { ClassKey key = new ClassKey(String.class); assertEquals(0, key.compareTo(key)); assertTrue(key.equals(key)); assertFalse(key.equals(null)); assertFalse(key.equals("foo")); assertFalse(key.equals(new ClassKey(Integer.class))); assertEquals(String.class.getName(), key.toString()); } // [databind#116] public void testJavaTypeAsJLRType() { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t1 = tf.constructType(getClass()); // should just get it back as-is: JavaType t2 = tf.constructType(t1); assertSame(t1, t2); } // [databind#1194] public void testGenericSignature1194() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); Method m; JavaType t; m = Generic1194.class.getMethod("getList"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/List;", t.getGenericSignature()); assertEquals("Ljava/util/List;", t.getErasedSignature()); m = Generic1194.class.getMethod("getMap"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/Map;", t.getGenericSignature()); m = Generic1194.class.getMethod("getGeneric"); t = tf.constructType(m.getGenericReturnType()); assertEquals("Ljava/util/concurrent/atomic/AtomicReference;", t.getGenericSignature()); } public void testAnchorTypeForRefTypes() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); JavaType t = tf.constructType(AtomicStringReference.class); assertTrue(t.isReferenceType()); assertTrue(t.hasContentType()); JavaType ct = t.getContentType(); assertEquals(String.class, ct.getRawClass()); assertSame(ct, t.containedType(0)); ReferenceType rt = (ReferenceType) t; assertFalse(rt.isAnchorType()); assertEquals(AtomicReference.class, rt.getAnchorType().getRawClass()); } // for [databind#1290] public void testObjectToReferenceSpecialization() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); JavaType base = tf.constructType(Object.class); assertTrue(base.isJavaLangObject()); JavaType sub = tf.constructSpecializedType(base, AtomicReference.class); assertEquals(AtomicReference.class, sub.getRawClass()); assertTrue(sub.isReferenceType()); } // for [databind#2091] public void testConstructReferenceType() throws Exception { TypeFactory tf = TypeFactory.defaultInstance(); // do AtomicReference final JavaType refdType = tf.constructType(Long.class); JavaType t = tf.constructReferenceType(AtomicReference.class, refdType); assertTrue(t.isReferenceType()); assertTrue(t.hasContentType()); assertEquals(Long.class, t.getContentType().getRawClass()); // 26-Mar-2020, tatu: [databind#2019] suggest this should be 1... // assertEquals(1, t.containedTypeCount()); } }