1 package com.fasterxml.jackson.databind.type;
2
3 import java.lang.reflect.TypeVariable;
4 import java.util.*;
5
6 import com.fasterxml.jackson.databind.JavaType;
7
8
16 public class MapLikeType extends TypeBase {
17 private static final long serialVersionUID = 1L;
18
19
22 protected final JavaType _keyType;
23
24
27 protected final JavaType _valueType;
28
29
34
35 protected MapLikeType(Class<?> mapType, TypeBindings bindings,
36 JavaType superClass, JavaType[] superInts, JavaType keyT,
37 JavaType valueT, Object valueHandler, Object typeHandler,
38 boolean asStatic) {
39 super(mapType, bindings, superClass, superInts, keyT.hashCode()
40 ^ valueT.hashCode(), valueHandler, typeHandler, asStatic);
41 _keyType = keyT;
42 _valueType = valueT;
43 }
44
45
48 protected MapLikeType(TypeBase base, JavaType keyT, JavaType valueT) {
49 super(base);
50 _keyType = keyT;
51 _valueType = valueT;
52 }
53
54
60 public static MapLikeType upgradeFrom(JavaType baseType, JavaType keyT,
61 JavaType valueT) {
62
63
64
65 if (baseType instanceof TypeBase) {
66 return new MapLikeType((TypeBase) baseType, keyT, valueT);
67 }
68 throw new IllegalArgumentException(
69 "Cannot upgrade from an instance of " + baseType.getClass());
70 }
71
72 @Deprecated
73
74 public static MapLikeType construct(Class<?> rawType, JavaType keyT,
75 JavaType valueT) {
76
77
78 TypeVariable<?>[] vars = rawType.getTypeParameters();
79 TypeBindings bindings;
80 if ((vars == null) || (vars.length != 2)) {
81 bindings = TypeBindings.emptyBindings();
82 } else {
83 bindings = TypeBindings.create(rawType, keyT, valueT);
84 }
85 return new MapLikeType(rawType, bindings, _bogusSuperClass(rawType),
86 null, keyT, valueT, null, null, false);
87 }
88
89 @Deprecated
90
91 @Override
92 protected JavaType _narrow(Class<?> subclass) {
93 return new MapLikeType(subclass, _bindings, _superClass,
94 _superInterfaces, _keyType, _valueType, _valueHandler,
95 _typeHandler, _asStatic);
96 }
97
98
101 public MapLikeType withKeyType(JavaType keyType) {
102 if (keyType == _keyType) {
103 return this;
104 }
105 return new MapLikeType(_class, _bindings, _superClass,
106 _superInterfaces, keyType, _valueType, _valueHandler,
107 _typeHandler, _asStatic);
108 }
109
110 @Override
111 public JavaType withContentType(JavaType contentType) {
112 if (_valueType == contentType) {
113 return this;
114 }
115 return new MapLikeType(_class, _bindings, _superClass,
116 _superInterfaces, _keyType, contentType, _valueHandler,
117 _typeHandler, _asStatic);
118 }
119
120 @Override
121 public MapLikeType withTypeHandler(Object h) {
122 return new MapLikeType(_class, _bindings, _superClass,
123 _superInterfaces, _keyType, _valueType, _valueHandler, h,
124 _asStatic);
125 }
126
127 @Override
128 public MapLikeType withContentTypeHandler(Object h) {
129 return new MapLikeType(_class, _bindings, _superClass,
130 _superInterfaces, _keyType, _valueType.withTypeHandler(h),
131 _valueHandler, _typeHandler, _asStatic);
132 }
133
134 @Override
135 public MapLikeType withValueHandler(Object h) {
136 return new MapLikeType(_class, _bindings, _superClass,
137 _superInterfaces, _keyType, _valueType, h, _typeHandler,
138 _asStatic);
139 }
140
141 @Override
142 public MapLikeType withContentValueHandler(Object h) {
143 return new MapLikeType(_class, _bindings, _superClass,
144 _superInterfaces, _keyType, _valueType.withValueHandler(h),
145 _valueHandler, _typeHandler, _asStatic);
146 }
147
148 @Override
149 public JavaType withHandlersFrom(JavaType src) {
150 JavaType type = super.withHandlersFrom(src);
151 JavaType srcKeyType = src.getKeyType();
152
153 if (type instanceof MapLikeType) {
154 if (srcKeyType != null) {
155 JavaType ct = _keyType.withHandlersFrom(srcKeyType);
156 if (ct != _keyType) {
157 type = ((MapLikeType) type).withKeyType(ct);
158 }
159 }
160 }
161 JavaType srcCt = src.getContentType();
162 if (srcCt != null) {
163 JavaType ct = _valueType.withHandlersFrom(srcCt);
164 if (ct != _valueType) {
165 type = type.withContentType(ct);
166 }
167 }
168 return type;
169 }
170
171 @Override
172 public MapLikeType withStaticTyping() {
173 if (_asStatic) {
174 return this;
175 }
176 return new MapLikeType(_class, _bindings, _superClass,
177 _superInterfaces, _keyType, _valueType.withStaticTyping(),
178 _valueHandler, _typeHandler, true);
179 }
180
181 @Override
182 public JavaType refine(Class<?> rawType, TypeBindings bindings,
183 JavaType superClass, JavaType[] superInterfaces) {
184 return new MapLikeType(rawType, bindings, superClass, superInterfaces,
185 _keyType, _valueType, _valueHandler, _typeHandler, _asStatic);
186 }
187
188 @Override
189 protected String buildCanonicalName() {
190 StringBuilder sb = new StringBuilder();
191 sb.append(_class.getName());
192 if (_keyType != null) {
193 sb.append('<');
194 sb.append(_keyType.toCanonical());
195 sb.append(',');
196 sb.append(_valueType.toCanonical());
197 sb.append('>');
198 }
199 return sb.toString();
200 }
201
202
207
208 @Override
209 public boolean isContainerType() {
210 return true;
211 }
212
213 @Override
214 public boolean isMapLikeType() {
215 return true;
216 }
217
218 @Override
219 public JavaType getKeyType() {
220 return _keyType;
221 }
222
223 @Override
224 public JavaType getContentType() {
225 return _valueType;
226 }
227
228 @Override
229 public Object getContentValueHandler() {
230 return _valueType.getValueHandler();
231 }
232
233 @Override
234 public Object getContentTypeHandler() {
235 return _valueType.getTypeHandler();
236 }
237
238 @Override
239 public boolean hasHandlers() {
240 return super.hasHandlers() || _valueType.hasHandlers()
241 || _keyType.hasHandlers();
242 }
243
244 @Override
245 public StringBuilder getErasedSignature(StringBuilder sb) {
246 return _classSignature(_class, sb, true);
247 }
248
249 @Override
250 public StringBuilder getGenericSignature(StringBuilder sb) {
251 _classSignature(_class, sb, false);
252 sb.append('<');
253 _keyType.getGenericSignature(sb);
254 _valueType.getGenericSignature(sb);
255 sb.append(">;");
256 return sb;
257 }
258
259
264
265 public MapLikeType withKeyTypeHandler(Object h) {
266 return new MapLikeType(_class, _bindings, _superClass,
267 _superInterfaces, _keyType.withTypeHandler(h), _valueType,
268 _valueHandler, _typeHandler, _asStatic);
269 }
270
271 public MapLikeType withKeyValueHandler(Object h) {
272 return new MapLikeType(_class, _bindings, _superClass,
273 _superInterfaces, _keyType.withValueHandler(h), _valueType,
274 _valueHandler, _typeHandler, _asStatic);
275 }
276
277
282 public boolean isTrueMapType() {
283 return Map.class.isAssignableFrom(_class);
284 }
285
286
291
292 @Override
293 public String toString() {
294 return String.format("[map-like type; class %s, %s -> %s]",
295 _class.getName(), _keyType, _valueType);
296 }
297
298 @Override
299 public boolean equals(Object o) {
300 if (o == this) return true;
301 if (o == null) return false;
302 if (o.getClass() != getClass()) return false;
303
304 MapLikeType other = (MapLikeType) o;
305 return (_class == other._class) && _keyType.equals(other._keyType)
306 && _valueType.equals(other._valueType);
307 }
308 }
309