1 package com.fasterxml.jackson.databind.type;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.core.JsonGenerator;
7 import com.fasterxml.jackson.core.JsonProcessingException;
8 import com.fasterxml.jackson.core.JsonToken;
9 import com.fasterxml.jackson.core.type.WritableTypeId;
10 import com.fasterxml.jackson.databind.*;
11 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
12 
13 public abstract class TypeBase
14     extends JavaType
15     implements JsonSerializable
16 {
17     private static final long serialVersionUID = 1;
18 
19     private final static TypeBindings NO_BINDINGS = TypeBindings.emptyBindings();
20     private final static JavaType[] NO_TYPES = new JavaType[0];
21 
22     protected final JavaType _superClass;
23 
24     protected final JavaType[] _superInterfaces;
25 
26     /**
27      * Bindings in effect for this type instance; possibly empty.
28      * Needed when resolving types declared in members of this type
29      * (if any).
30      *
31      * @since 2.7
32      */
33     protected final TypeBindings _bindings;
34 
35     /**
36      * Lazily initialized external representation of the type
37      */
38     volatile transient String _canonicalName;
39 
40     /**
41      * Main constructor to use by extending classes.
42      */
TypeBase(Class<?> raw, TypeBindings bindings, JavaType superClass, JavaType[] superInts, int hash, Object valueHandler, Object typeHandler, boolean asStatic)43     protected TypeBase(Class<?> raw, TypeBindings bindings, JavaType superClass, JavaType[] superInts,
44             int hash,
45             Object valueHandler, Object typeHandler, boolean asStatic)
46     {
47         super(raw, hash, valueHandler, typeHandler, asStatic);
48         _bindings = (bindings == null) ? NO_BINDINGS : bindings;
49         _superClass = superClass;
50         _superInterfaces = superInts;
51     }
52 
53     /**
54      * Copy-constructor used when refining/upgrading type instances.
55      *
56      * @since 2.7
57      */
TypeBase(TypeBase base)58     protected TypeBase(TypeBase base) {
59         super(base);
60         _superClass = base._superClass;
61         _superInterfaces = base._superInterfaces;
62         _bindings = base._bindings;
63     }
64 
65     @Override
toCanonical()66     public String toCanonical()
67     {
68         String str = _canonicalName;
69         if (str == null) {
70             str = buildCanonicalName();
71         }
72         return str;
73     }
74 
buildCanonicalName()75     protected String buildCanonicalName() {
76         return _class.getName();
77     }
78 
79     @Override
getGenericSignature(StringBuilder sb)80     public abstract StringBuilder getGenericSignature(StringBuilder sb);
81 
82     @Override
getErasedSignature(StringBuilder sb)83     public abstract StringBuilder getErasedSignature(StringBuilder sb);
84 
85     @Override
getBindings()86     public TypeBindings getBindings() {
87         return _bindings;
88     }
89 
90     @Override
containedTypeCount()91     public int containedTypeCount() {
92         return _bindings.size();
93     }
94 
95     @Override
containedType(int index)96     public JavaType containedType(int index) {
97         return _bindings.getBoundType(index);
98     }
99 
100     @Override
101     @Deprecated
containedTypeName(int index)102     public String containedTypeName(int index) {
103         return _bindings.getBoundName(index);
104     }
105 
106     @Override
getSuperClass()107     public JavaType getSuperClass() {
108         return _superClass;
109     }
110 
111     @Override
getInterfaces()112     public List<JavaType> getInterfaces() {
113         if (_superInterfaces == null) {
114             return Collections.emptyList();
115         }
116         switch (_superInterfaces.length) {
117         case 0:
118             return Collections.emptyList();
119         case 1:
120             return Collections.singletonList(_superInterfaces[0]);
121         }
122         return Arrays.asList(_superInterfaces);
123     }
124 
125     @Override
findSuperType(Class<?> rawTarget)126     public final JavaType findSuperType(Class<?> rawTarget)
127     {
128         if (rawTarget == _class) {
129             return this;
130         }
131         // Check super interfaces first:
132         if (rawTarget.isInterface() && (_superInterfaces != null)) {
133             for (int i = 0, count = _superInterfaces.length; i < count; ++i) {
134                 JavaType type = _superInterfaces[i].findSuperType(rawTarget);
135                 if (type != null) {
136                     return type;
137                 }
138             }
139         }
140         // and if not found, super class and its supertypes
141         if (_superClass != null) {
142             JavaType type = _superClass.findSuperType(rawTarget);
143             if (type != null) {
144                 return type;
145             }
146         }
147         return null;
148     }
149 
150     @Override
findTypeParameters(Class<?> expType)151     public JavaType[] findTypeParameters(Class<?> expType)
152     {
153         JavaType match = findSuperType(expType);
154         if (match == null) {
155             return NO_TYPES;
156         }
157         return match.getBindings().typeParameterArray();
158     }
159 
160     /*
161     /**********************************************************
162     /* JsonSerializable base implementation
163     /**********************************************************
164      */
165 
166     @Override
serializeWithType(JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer)167     public void serializeWithType(JsonGenerator g, SerializerProvider provider,
168             TypeSerializer typeSer)
169         throws IOException
170     {
171         WritableTypeId typeIdDef = new WritableTypeId(this, JsonToken.VALUE_STRING);
172         typeSer.writeTypePrefix(g, typeIdDef);
173         this.serialize(g, provider);
174         typeSer.writeTypeSuffix(g, typeIdDef);
175     }
176 
177     @Override
serialize(JsonGenerator gen, SerializerProvider provider)178     public void serialize(JsonGenerator gen, SerializerProvider provider)
179             throws IOException, JsonProcessingException
180     {
181         gen.writeString(toCanonical());
182     }
183 
184     /*
185     /**********************************************************
186     /* Methods for sub-classes to use
187     /**********************************************************
188      */
189 
190     /**
191      * @param trailingSemicolon Whether to add trailing semicolon for non-primitive
192      *   (reference) types or not
193      */
_classSignature(Class<?> cls, StringBuilder sb, boolean trailingSemicolon)194     protected static StringBuilder _classSignature(Class<?> cls, StringBuilder sb,
195            boolean trailingSemicolon)
196     {
197         if (cls.isPrimitive()) {
198             if (cls == Boolean.TYPE) {
199                 sb.append('Z');
200             } else if (cls == Byte.TYPE) {
201                 sb.append('B');
202             }
203             else if (cls == Short.TYPE) {
204                 sb.append('S');
205             }
206             else if (cls == Character.TYPE) {
207                 sb.append('C');
208             }
209             else if (cls == Integer.TYPE) {
210                 sb.append('I');
211             }
212             else if (cls == Long.TYPE) {
213                 sb.append('J');
214             }
215             else if (cls == Float.TYPE) {
216                 sb.append('F');
217             }
218             else if (cls == Double.TYPE) {
219                 sb.append('D');
220             }
221             else if (cls == Void.TYPE) {
222                 sb.append('V');
223             } else {
224                 throw new IllegalStateException("Unrecognized primitive type: "+cls.getName());
225             }
226         } else {
227             sb.append('L');
228             String name = cls.getName();
229             for (int i = 0, len = name.length(); i < len; ++i) {
230                 char c = name.charAt(i);
231                 if (c == '.') c = '/';
232                 sb.append(c);
233             }
234             if (trailingSemicolon) {
235                 sb.append(';');
236             }
237         }
238         return sb;
239     }
240 
241     /**
242      * Internal helper method used to figure out nominal super-class for
243      * deprecated factory methods / constructors, where we are not given
244      * properly resolved supertype hierarchy.
245      * Will basically give `JavaType` for `java.lang.Object` for classes
246      * other than `java.lafgn.Object`; null for others.
247      *
248      * @since 2.7
249      */
_bogusSuperClass(Class<?> cls)250     protected static JavaType _bogusSuperClass(Class<?> cls) {
251         Class<?> parent = cls.getSuperclass();
252         if (parent == null) {
253             return null;
254         }
255         return TypeFactory.unknownType();
256     }
257 }
258