1 package com.fasterxml.jackson.databind.type; 2 3 import com.fasterxml.jackson.databind.JavaType; 4 5 /** 6 * Internal placeholder type used for self-references. 7 * 8 * @since 2.7 9 */ 10 public class ResolvedRecursiveType extends TypeBase 11 { 12 private static final long serialVersionUID = 1L; 13 14 protected JavaType _referencedType; 15 ResolvedRecursiveType(Class<?> erasedType, TypeBindings bindings)16 public ResolvedRecursiveType(Class<?> erasedType, TypeBindings bindings) { 17 super(erasedType, bindings, null, null, 0, null, null, false); 18 } 19 setReference(JavaType ref)20 public void setReference(JavaType ref) 21 { 22 // sanity check; should not be called multiple times 23 if (_referencedType != null) { 24 throw new IllegalStateException("Trying to re-set self reference; old value = "+_referencedType+", new = "+ref); 25 } 26 _referencedType = ref; 27 } 28 29 @Override getSuperClass()30 public JavaType getSuperClass() { 31 if (_referencedType != null) { 32 return _referencedType.getSuperClass(); 33 } 34 return super.getSuperClass(); 35 } 36 getSelfReferencedType()37 public JavaType getSelfReferencedType() { return _referencedType; } 38 39 // 23-Jul-2019, tatu: [databind#2331] Need to also delegate this... 40 @Override getBindings()41 public TypeBindings getBindings() { 42 if (_referencedType != null) { // `null` before resolution [databind#2395] 43 return _referencedType.getBindings(); 44 } 45 return super.getBindings(); 46 } 47 48 @Override getGenericSignature(StringBuilder sb)49 public StringBuilder getGenericSignature(StringBuilder sb) { 50 // 30-Oct-2019, tatu: Alas, need to break recursion, otherwise we'll 51 // end up in StackOverflowError... two choices; '?' for "not known", 52 // or erased signature. 53 if (_referencedType != null) { 54 // return _referencedType.getGenericSignature(sb); 55 return _referencedType.getErasedSignature(sb); 56 } 57 return sb.append("?"); 58 } 59 60 @Override getErasedSignature(StringBuilder sb)61 public StringBuilder getErasedSignature(StringBuilder sb) { 62 if (_referencedType != null) { 63 return _referencedType.getErasedSignature(sb); 64 } 65 return sb; 66 } 67 68 @Override withContentType(JavaType contentType)69 public JavaType withContentType(JavaType contentType) { 70 return this; 71 } 72 73 @Override withTypeHandler(Object h)74 public JavaType withTypeHandler(Object h) { 75 return this; 76 } 77 78 @Override withContentTypeHandler(Object h)79 public JavaType withContentTypeHandler(Object h) { 80 return this; 81 } 82 83 @Override withValueHandler(Object h)84 public JavaType withValueHandler(Object h) { 85 return this; 86 } 87 88 @Override withContentValueHandler(Object h)89 public JavaType withContentValueHandler(Object h) { 90 return this; 91 } 92 93 @Override withStaticTyping()94 public JavaType withStaticTyping() { 95 return this; 96 } 97 98 @Deprecated // since 2.7 99 @Override _narrow(Class<?> subclass)100 protected JavaType _narrow(Class<?> subclass) { 101 return this; 102 } 103 104 @Override refine(Class<?> rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces)105 public JavaType refine(Class<?> rawType, TypeBindings bindings, 106 JavaType superClass, JavaType[] superInterfaces) { 107 return null; 108 } 109 110 @Override isContainerType()111 public boolean isContainerType() { 112 return false; 113 } 114 115 @Override toString()116 public String toString() { 117 StringBuilder sb = new StringBuilder(40) 118 .append("[recursive type; "); 119 if (_referencedType == null) { 120 sb.append("UNRESOLVED"); 121 } else { 122 // [databind#1301]: Typically resolves to a loop so short-cut 123 // and only include type-erased class 124 sb.append(_referencedType.getRawClass().getName()); 125 } 126 return sb.toString(); 127 } 128 129 @Override equals(Object o)130 public boolean equals(Object o) { 131 if (o == this) return true; 132 if (o == null) return false; 133 if (o.getClass() == getClass()) { 134 // 16-Jun-2017, tatu: as per [databind#1658], cannot do recursive call since 135 // there is likely to be a cycle... 136 137 // but... true or false? 138 return false; 139 140 /* 141 // Do NOT ever match unresolved references 142 if (_referencedType == null) { 143 return false; 144 } 145 return (o.getClass() == getClass() 146 && _referencedType.equals(((ResolvedRecursiveType) o).getSelfReferencedType())); 147 */ 148 } 149 return false; 150 } 151 } 152