TypeIdResolverBase.java
package com.fasterxml.jackson.databind.jsontype.impl;
import java.io.IOException;
import com.fasterxml.jackson.databind.DatabindContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Partial base implementation of {@link TypeIdResolver}: all custom implementations
* are <b>strongly</b> recommended to extend this class, instead of directly
* implementing {@link TypeIdResolver}.
* Note that ALL sub-class need to re-implement
* {@link #typeFromId(DatabindContext, String)} method; otherwise implementation
* will not work.
*<p>
* Note that instances created to be constructed from annotations
* ({@link com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver})
* are always created using no-arguments constructor; protected constructor
* is only used sub-classes.
*/
public abstract class TypeIdResolverBase
implements TypeIdResolver
{
protected final TypeFactory _typeFactory;
/**
* Common base type for all polymorphic instances handled.
*/
protected final JavaType _baseType;
protected TypeIdResolverBase() {
this(null, null);
}
protected TypeIdResolverBase(JavaType baseType, TypeFactory typeFactory) {
_baseType = baseType;
_typeFactory = typeFactory;
}
// Standard type id resolvers do not need this: only useful for custom ones.
@Override
public void init(JavaType bt) { }
@Override
public String idFromBaseType() {
/* By default we will just defer to regular handling, handing out the
* base type; and since there is no value, must just pass null here
* assuming that implementations can deal with it.
* Alternative would be to pass a bogus Object, but that does not seem right.
*/
return idFromValueAndType(null, _baseType.getRawClass());
}
@Override
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
// 22-Dec-2015, tatu: Must be overridden by sub-classes, so let's throw
// an exception if not
throw new IllegalStateException("Sub-class "+getClass().getName()+" MUST implement "
+"`typeFromId(DatabindContext,String)");
}
/**
* Helper method used to get a simple description of all known type ids,
* for use in error messages.
*/
@Override
public String getDescForKnownTypeIds() {
return null;
}
/**
* Helper method for ensuring we properly resolve cases where we don't
* want to use given instance class due to it being a specific inner class
* but rather enclosing (or parent) class. Specific case we know of
* currently are "enum subtypes", cases
* where simple Enum constant has overrides and uses generated sub-class
* if parent Enum type. In this case we need to ensure that we use
* the main/parent Enum type, not sub-class.
*
* @param cls Class to check and possibly resolve
* @return Resolved class to use
* @since 2.18.2
*/
protected Class<?> _resolveToParentAsNecessary(Class<?> cls) {
// Need to ensure that "enum subtypes" work too
if (ClassUtil.isEnumType(cls)) {
// 29-Sep-2019, tatu: `Class.isEnum()` only returns true for main declaration,
// but NOT from sub-class thereof (extending individual values). This
// is why additional resolution is needed: we want class that contains
// enumeration instances.
if (!cls.isEnum()) {
// and this parent would then have `Enum.class` as its parent:
cls = cls.getSuperclass();
}
}
return cls;
}
}