| package com.fasterxml.jackson.databind.type; |
| |
| import java.io.IOException; |
| import java.util.*; |
| |
| import com.fasterxml.jackson.core.JsonGenerator; |
| import com.fasterxml.jackson.core.JsonProcessingException; |
| import com.fasterxml.jackson.databind.*; |
| import com.fasterxml.jackson.databind.jsontype.TypeSerializer; |
| |
| public abstract class TypeBase |
| extends JavaType |
| implements JsonSerializable |
| { |
| private static final long serialVersionUID = 1; |
| |
| private final static TypeBindings NO_BINDINGS = TypeBindings.emptyBindings(); |
| private final static JavaType[] NO_TYPES = new JavaType[0]; |
| |
| protected final JavaType _superClass; |
| |
| protected final JavaType[] _superInterfaces; |
| |
| /** |
| * Bindings in effect for this type instance; possibly empty. |
| * Needed when resolving types declared in members of this type |
| * (if any). |
| * |
| * @since 2.7 |
| */ |
| protected final TypeBindings _bindings; |
| |
| /** |
| * Lazily initialized external representation of the type |
| */ |
| volatile transient String _canonicalName; |
| |
| /** |
| * Main constructor to use by extending classes. |
| */ |
| protected TypeBase(Class<?> raw, TypeBindings bindings, JavaType superClass, JavaType[] superInts, |
| int hash, |
| Object valueHandler, Object typeHandler, boolean asStatic) |
| { |
| super(raw, hash, valueHandler, typeHandler, asStatic); |
| _bindings = (bindings == null) ? NO_BINDINGS : bindings; |
| _superClass = superClass; |
| _superInterfaces = superInts; |
| } |
| |
| /** |
| * Copy-constructor used when refining/upgrading type instances. |
| * |
| * @since 2.7 |
| */ |
| protected TypeBase(TypeBase base) { |
| super(base); |
| _superClass = base._superClass; |
| _superInterfaces = base._superInterfaces; |
| _bindings = base._bindings; |
| } |
| |
| @Override |
| public String toCanonical() |
| { |
| String str = _canonicalName; |
| if (str == null) { |
| str = buildCanonicalName(); |
| } |
| return str; |
| } |
| |
| protected String buildCanonicalName() { |
| return _class.getName(); |
| } |
| |
| @Override |
| public abstract StringBuilder getGenericSignature(StringBuilder sb); |
| |
| @Override |
| public abstract StringBuilder getErasedSignature(StringBuilder sb); |
| |
| @Override |
| public TypeBindings getBindings() { |
| return _bindings; |
| } |
| |
| @Override |
| public int containedTypeCount() { |
| return _bindings.size(); |
| } |
| |
| @Override |
| public JavaType containedType(int index) { |
| return _bindings.getBoundType(index); |
| } |
| |
| @Override |
| @Deprecated |
| public String containedTypeName(int index) { |
| return _bindings.getBoundName(index); |
| } |
| |
| @Override |
| public JavaType getSuperClass() { |
| return _superClass; |
| } |
| |
| @Override |
| public List<JavaType> getInterfaces() { |
| if (_superInterfaces == null) { |
| return Collections.emptyList(); |
| } |
| switch (_superInterfaces.length) { |
| case 0: |
| return Collections.emptyList(); |
| case 1: |
| return Collections.singletonList(_superInterfaces[0]); |
| } |
| return Arrays.asList(_superInterfaces); |
| } |
| |
| @Override |
| public final JavaType findSuperType(Class<?> rawTarget) |
| { |
| if (rawTarget == _class) { |
| return this; |
| } |
| // Check super interfaces first: |
| if (rawTarget.isInterface() && (_superInterfaces != null)) { |
| for (int i = 0, count = _superInterfaces.length; i < count; ++i) { |
| JavaType type = _superInterfaces[i].findSuperType(rawTarget); |
| if (type != null) { |
| return type; |
| } |
| } |
| } |
| // and if not found, super class and its supertypes |
| if (_superClass != null) { |
| JavaType type = _superClass.findSuperType(rawTarget); |
| if (type != null) { |
| return type; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public JavaType[] findTypeParameters(Class<?> expType) |
| { |
| JavaType match = findSuperType(expType); |
| if (match == null) { |
| return NO_TYPES; |
| } |
| return match.getBindings().typeParameterArray(); |
| } |
| |
| /* |
| /********************************************************** |
| /* JsonSerializable base implementation |
| /********************************************************** |
| */ |
| |
| @Override |
| public void serializeWithType(JsonGenerator gen, SerializerProvider provider, |
| TypeSerializer typeSer) |
| throws IOException, JsonProcessingException |
| { |
| typeSer.writeTypePrefixForScalar(this, gen); |
| this.serialize(gen, provider); |
| typeSer.writeTypeSuffixForScalar(this, gen); |
| } |
| |
| @Override |
| public void serialize(JsonGenerator gen, SerializerProvider provider) |
| throws IOException, JsonProcessingException |
| { |
| gen.writeString(toCanonical()); |
| } |
| |
| /* |
| /********************************************************** |
| /* Methods for sub-classes to use |
| /********************************************************** |
| */ |
| |
| /** |
| * @param trailingSemicolon Whether to add trailing semicolon for non-primitive |
| * (reference) types or not |
| */ |
| protected static StringBuilder _classSignature(Class<?> cls, StringBuilder sb, |
| boolean trailingSemicolon) |
| { |
| if (cls.isPrimitive()) { |
| if (cls == Boolean.TYPE) { |
| sb.append('Z'); |
| } else if (cls == Byte.TYPE) { |
| sb.append('B'); |
| } |
| else if (cls == Short.TYPE) { |
| sb.append('S'); |
| } |
| else if (cls == Character.TYPE) { |
| sb.append('C'); |
| } |
| else if (cls == Integer.TYPE) { |
| sb.append('I'); |
| } |
| else if (cls == Long.TYPE) { |
| sb.append('J'); |
| } |
| else if (cls == Float.TYPE) { |
| sb.append('F'); |
| } |
| else if (cls == Double.TYPE) { |
| sb.append('D'); |
| } |
| else if (cls == Void.TYPE) { |
| sb.append('V'); |
| } else { |
| throw new IllegalStateException("Unrecognized primitive type: "+cls.getName()); |
| } |
| } else { |
| sb.append('L'); |
| String name = cls.getName(); |
| for (int i = 0, len = name.length(); i < len; ++i) { |
| char c = name.charAt(i); |
| if (c == '.') c = '/'; |
| sb.append(c); |
| } |
| if (trailingSemicolon) { |
| sb.append(';'); |
| } |
| } |
| return sb; |
| } |
| |
| /** |
| * Internal helper method used to figure out nominal super-class for |
| * deprecated factory methods / constructors, where we are not given |
| * properly resolved supertype hierarchy. |
| * Will basically give `JavaType` for `java.lang.Object` for classes |
| * other than `java.lafgn.Object`; null for others. |
| * |
| * @since 2.7 |
| */ |
| protected static JavaType _bogusSuperClass(Class<?> cls) { |
| Class<?> parent = cls.getSuperclass(); |
| if (parent == null) { |
| return null; |
| } |
| return TypeFactory.unknownType(); |
| } |
| } |