package com.fasterxml.jackson.databind.type;

import com.fasterxml.jackson.databind.JavaType;

Internal placeholder type used for self-references.
Since:2.7
/** * Internal placeholder type used for self-references. * * @since 2.7 */
public class ResolvedRecursiveType extends TypeBase { private static final long serialVersionUID = 1L; protected JavaType _referencedType; public ResolvedRecursiveType(Class<?> erasedType, TypeBindings bindings) { super(erasedType, bindings, null, null, 0, null, null, false); } public void setReference(JavaType ref) { // sanity check; should not be called multiple times if (_referencedType != null) { throw new IllegalStateException("Trying to re-set self reference; old value = "+_referencedType+", new = "+ref); } _referencedType = ref; } @Override public JavaType getSuperClass() { if (_referencedType != null) { return _referencedType.getSuperClass(); } return super.getSuperClass(); } public JavaType getSelfReferencedType() { return _referencedType; } // 23-Jul-2019, tatu: [databind#2331] Need to also delegate this... @Override public TypeBindings getBindings() { if (_referencedType != null) { // `null` before resolution [databind#2395] return _referencedType.getBindings(); } return super.getBindings(); } @Override public StringBuilder getGenericSignature(StringBuilder sb) { // 30-Oct-2019, tatu: Alas, need to break recursion, otherwise we'll // end up in StackOverflowError... two choices; '?' for "not known", // or erased signature. if (_referencedType != null) { // return _referencedType.getGenericSignature(sb); return _referencedType.getErasedSignature(sb); } return sb.append("?"); } @Override public StringBuilder getErasedSignature(StringBuilder sb) { if (_referencedType != null) { return _referencedType.getErasedSignature(sb); } return sb; } @Override public JavaType withContentType(JavaType contentType) { return this; } @Override public JavaType withTypeHandler(Object h) { return this; } @Override public JavaType withContentTypeHandler(Object h) { return this; } @Override public JavaType withValueHandler(Object h) { return this; } @Override public JavaType withContentValueHandler(Object h) { return this; } @Override public JavaType withStaticTyping() { return this; } @Deprecated // since 2.7 @Override protected JavaType _narrow(Class<?> subclass) { return this; } @Override public JavaType refine(Class<?> rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { return null; } @Override public boolean isContainerType() { return false; } @Override public String toString() { StringBuilder sb = new StringBuilder(40) .append("[recursive type; "); if (_referencedType == null) { sb.append("UNRESOLVED"); } else { // [databind#1301]: Typically resolves to a loop so short-cut // and only include type-erased class sb.append(_referencedType.getRawClass().getName()); } return sb.toString(); } @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; if (o.getClass() == getClass()) { // 16-Jun-2017, tatu: as per [databind#1658], cannot do recursive call since // there is likely to be a cycle... // but... true or false? return false; /* // Do NOT ever match unresolved references if (_referencedType == null) { return false; } return (o.getClass() == getClass() && _referencedType.equals(((ResolvedRecursiveType) o).getSelfReferencedType())); */ } return false; } }