1 package com.fasterxml.jackson.databind; 2 3 import java.lang.reflect.Modifier; 4 import java.util.List; 5 6 import com.fasterxml.jackson.core.type.ResolvedType; 7 import com.fasterxml.jackson.databind.type.TypeBindings; 8 import com.fasterxml.jackson.databind.type.TypeFactory; 9 import com.fasterxml.jackson.databind.util.ClassUtil; 10 11 /** 12 * Base class for type token classes used both to contain information 13 * and as keys for deserializers. 14 *<p> 15 * Instances can (only) be constructed by 16 * <code>com.fasterxml.jackson.databind.type.TypeFactory</code>. 17 *<p> 18 * Since 2.2 this implements {@link java.lang.reflect.Type} to allow 19 * it to be pushed through interfaces that only expose that type. 20 */ 21 public abstract class JavaType 22 extends ResolvedType 23 implements java.io.Serializable, // 2.1 24 java.lang.reflect.Type // 2.2 25 { 26 private static final long serialVersionUID = 1; 27 28 /** 29 * This is the nominal type-erased Class that would be close to the 30 * type represented (but not exactly type, due to type erasure: type 31 * instance may have more information on this). 32 * May be an interface or abstract class, so instantiation 33 * may not be possible. 34 */ 35 protected final Class<?> _class; 36 37 protected final int _hash; 38 39 /** 40 * Optional handler (codec) that can be attached to indicate 41 * what to use for handling (serializing, deserializing) values of 42 * this specific type. 43 *<p> 44 * Note: untyped (i.e. caller has to cast) because it is used for 45 * different kinds of handlers, with unrelated types. 46 */ 47 protected final Object _valueHandler; 48 49 /** 50 * Optional handler that can be attached to indicate how to handle 51 * additional type metadata associated with this type. 52 *<p> 53 * Note: untyped (i.e. caller has to cast) because it is used for 54 * different kinds of handlers, with unrelated types. 55 */ 56 protected final Object _typeHandler; 57 58 /** 59 * Whether entities defined with this type should be handled using 60 * static typing (as opposed to dynamic runtime type) or not. 61 * 62 * @since 2.2 63 */ 64 protected final boolean _asStatic; 65 66 /* 67 /********************************************************** 68 /* Life-cycle 69 /********************************************************** 70 */ 71 72 /** 73 * @param raw "Raw" (type-erased) class for this type 74 * @param additionalHash Additional hash code to use, in addition 75 * to hash code of the class name 76 */ JavaType(Class<?> raw, int additionalHash, Object valueHandler, Object typeHandler, boolean asStatic)77 protected JavaType(Class<?> raw, int additionalHash, 78 Object valueHandler, Object typeHandler, boolean asStatic) 79 { 80 _class = raw; 81 _hash = raw.getName().hashCode() + additionalHash; 82 _valueHandler = valueHandler; 83 _typeHandler = typeHandler; 84 _asStatic = asStatic; 85 } 86 87 /** 88 * Copy-constructor used when refining/upgrading type instances. 89 * 90 * @since 2.7 91 */ JavaType(JavaType base)92 protected JavaType(JavaType base) 93 { 94 _class = base._class; 95 _hash = base._hash; 96 _valueHandler = base._valueHandler; 97 _typeHandler = base._typeHandler; 98 _asStatic = base._asStatic; 99 } 100 101 /** 102 * "Copy method" that will construct a new instance that is identical to 103 * this instance, except that it will have specified type handler assigned. 104 * 105 * @return Newly created type instance 106 */ withTypeHandler(Object h)107 public abstract JavaType withTypeHandler(Object h); 108 109 /** 110 * Mutant factory method that will construct a new instance that is identical to 111 * this instance, except that it will have specified content type (element type 112 * for arrays, value type for Maps and so forth) handler assigned. 113 * 114 * @return Newly created type instance, with given 115 */ withContentTypeHandler(Object h)116 public abstract JavaType withContentTypeHandler(Object h); 117 118 /** 119 * Mutant factory method that will construct a new instance that is identical to 120 * this instance, except that it will have specified value handler assigned. 121 * 122 * @return Newly created type instance 123 */ withValueHandler(Object h)124 public abstract JavaType withValueHandler(Object h); 125 126 /** 127 * Mutant factory method that will construct a new instance that is identical to 128 * this instance, except that it will have specified content value handler assigned. 129 * 130 * @return Newly created type instance 131 */ withContentValueHandler(Object h)132 public abstract JavaType withContentValueHandler(Object h); 133 134 /** 135 * Mutant factory method that will try to copy handlers that the specified 136 * source type instance had, if any; this must be done recursively where 137 * necessary (as content types may be structured). 138 * 139 * @since 2.8.4 140 */ withHandlersFrom(JavaType src)141 public JavaType withHandlersFrom(JavaType src) { 142 JavaType type = this; 143 Object h = src.getTypeHandler(); 144 if (h != _typeHandler) { 145 type = type.withTypeHandler(h); 146 } 147 h = src.getValueHandler(); 148 if (h != _valueHandler) { 149 type = type.withValueHandler(h); 150 } 151 return type; 152 } 153 154 /** 155 * Mutant factory method that may be called on structured types 156 * that have a so-called content type (element of arrays, value type 157 * of Maps, referenced type of referential types), 158 * and will construct a new instance that is identical to 159 * this instance, except that it has specified content type, instead of current 160 * one. If content type is already set to given type, <code>this</code> is returned. 161 * If type does not have a content type (which is the case with 162 * <code>SimpleType</code>), {@link IllegalArgumentException} 163 * will be thrown. 164 * 165 * @return Newly created type instance 166 * 167 * @since 2.7 168 */ withContentType(JavaType contentType)169 public abstract JavaType withContentType(JavaType contentType); 170 171 /** 172 * Method that can be called to get a type instance that indicates 173 * that values of the type should be handled using "static typing" for purposes 174 * of serialization (as opposed to "dynamic" aka runtime typing): 175 * meaning that no runtime information is needed for determining serializers to use. 176 * The main use case is to allow forcing of specific root value serialization type, 177 * and specifically in resolving serializers for contained types (element types 178 * for arrays, Collections and Maps). 179 * 180 * @since 2.2 181 */ withStaticTyping()182 public abstract JavaType withStaticTyping(); 183 184 /* 185 /********************************************************** 186 /* Type coercion fluent factory methods 187 /********************************************************** 188 */ 189 190 /** 191 * Mutant factory method that will try to create and return a sub-type instance 192 * for known parameterized types; for other types will return `null` to indicate 193 * that no just refinement makes necessary sense, without trying to detect 194 * special status through implemented interfaces. 195 * 196 * @since 2.7 197 */ refine(Class<?> rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces)198 public abstract JavaType refine(Class<?> rawType, TypeBindings bindings, 199 JavaType superClass, JavaType[] superInterfaces); 200 201 /** 202 * Legacy method used for forcing sub-typing of this type into 203 * type specified by specific type erasure. 204 * Deprecated as of 2.7 as such specializations really ought to 205 * go through {@link TypeFactory}, not directly via {@link JavaType}. 206 * 207 * @since 2.7 208 */ 209 @Deprecated forcedNarrowBy(Class<?> subclass)210 public JavaType forcedNarrowBy(Class<?> subclass) 211 { 212 if (subclass == _class) { // can still optimize for simple case 213 return this; 214 } 215 return _narrow(subclass); 216 } 217 218 @Deprecated // since 2.7 _narrow(Class<?> subclass)219 protected abstract JavaType _narrow(Class<?> subclass); 220 221 /* 222 /********************************************************** 223 /* Implementation of ResolvedType API 224 /********************************************************** 225 */ 226 227 @Override getRawClass()228 public final Class<?> getRawClass() { return _class; } 229 230 /** 231 * Method that can be used to check whether this type has 232 * specified Class as its type erasure. Put another way, returns 233 * true if instantiation of this Type is given (type-erased) Class. 234 */ 235 @Override hasRawClass(Class<?> clz)236 public final boolean hasRawClass(Class<?> clz) { return _class == clz; } 237 238 /** 239 * Accessor that allows determining whether {@link #getContentType()} should 240 * return a non-null value (that is, there is a "content type") or not. 241 * True if {@link #isContainerType()} or {@link #isReferenceType()} return true. 242 * 243 * @since 2.8 244 */ hasContentType()245 public boolean hasContentType() { 246 return true; 247 } 248 249 /** 250 * @since 2.6 251 */ isTypeOrSubTypeOf(Class<?> clz)252 public final boolean isTypeOrSubTypeOf(Class<?> clz) { 253 return (_class == clz) || clz.isAssignableFrom(_class); 254 } 255 256 /** 257 * @since 2.9 258 */ isTypeOrSuperTypeOf(Class<?> clz)259 public final boolean isTypeOrSuperTypeOf(Class<?> clz) { 260 return (_class == clz) || _class.isAssignableFrom(clz); 261 } 262 263 @Override isAbstract()264 public boolean isAbstract() { 265 return Modifier.isAbstract(_class.getModifiers()); 266 } 267 268 /** 269 * Convenience method for checking whether underlying Java type 270 * is a concrete class or not: abstract classes and interfaces 271 * are not. 272 */ 273 @Override isConcrete()274 public boolean isConcrete() { 275 int mod = _class.getModifiers(); 276 if ((mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0) { 277 return true; 278 } 279 /* 19-Feb-2010, tatus: Holy mackarel; primitive types 280 * have 'abstract' flag set... 281 */ 282 return _class.isPrimitive(); 283 } 284 285 @Override isThrowable()286 public boolean isThrowable() { return Throwable.class.isAssignableFrom(_class); } 287 288 @Override isArrayType()289 public boolean isArrayType() { return false; } 290 291 /** 292 * Method that basically does equivalent of: 293 *<pre> 294 * Enum.class.isAssignableFrom(getRawClass()) 295 *</pre> 296 * that is, return {@code true} if the underlying type erased class is {@code Enum} 297 * or one its subtypes (Enum implementations). 298 */ 299 @Override isEnumType()300 public final boolean isEnumType() { 301 // 29-Sep-2019, tatu: `Class.isEnum()` not enough to detect custom subtypes. 302 return ClassUtil.isEnumType(_class); 303 } 304 305 /** 306 * Similar to {@link #isEnumType} except does NOT return {@code true} 307 * for {@link java.lang.Enum} (since that is not Enum implementation type). 308 * 309 * @since 2.11 310 */ isEnumImplType()311 public final boolean isEnumImplType() { 312 return ClassUtil.isEnumType(_class) && (_class != Enum.class); 313 } 314 315 @Override isInterface()316 public final boolean isInterface() { return _class.isInterface(); } 317 318 @Override isPrimitive()319 public final boolean isPrimitive() { return _class.isPrimitive(); } 320 321 @Override isFinal()322 public final boolean isFinal() { return Modifier.isFinal(_class.getModifiers()); } 323 324 /** 325 * @return True if type represented is a container type; this includes 326 * array, Map and Collection types. 327 */ 328 @Override isContainerType()329 public abstract boolean isContainerType(); 330 331 /** 332 * @return True if type is either true {@link java.util.Collection} type, 333 * or something similar (meaning it has at least one type parameter, 334 * which describes type of contents) 335 */ 336 @Override isCollectionLikeType()337 public boolean isCollectionLikeType() { return false; } 338 339 /** 340 * @return True if type is either true {@link java.util.Map} type, 341 * or something similar (meaning it has at least two type parameter; 342 * first one describing key type, second value type) 343 */ 344 @Override isMapLikeType()345 public boolean isMapLikeType() { return false; } 346 347 /** 348 * Convenience method, short-hand for 349 *<code> 350 * getRawClass() == Object.class 351 *</code> 352 * and used to figure if we basically have "untyped" type object. 353 * 354 * @since 2.5 355 */ isJavaLangObject()356 public final boolean isJavaLangObject() { return _class == Object.class; } 357 358 /** 359 * Accessor for checking whether handlers for dealing with values of 360 * this type should use static typing (as opposed to dynamic typing). 361 * Note that while value of 'true' does mean that static typing is to 362 * be used, value of 'false' may still be overridden by other settings. 363 * 364 * @since 2.2 365 */ useStaticType()366 public final boolean useStaticType() { return _asStatic; } 367 368 /* 369 /********************************************************** 370 /* Public API, type parameter access; pass-through 371 /********************************************************** 372 */ 373 374 @Override hasGenericTypes()375 public boolean hasGenericTypes() { return containedTypeCount() > 0; } 376 377 @Override getKeyType()378 public JavaType getKeyType() { return null; } 379 380 @Override getContentType()381 public JavaType getContentType() { return null; } 382 383 @Override // since 2.6 getReferencedType()384 public JavaType getReferencedType() { return null; } 385 386 @Override containedTypeCount()387 public abstract int containedTypeCount(); 388 389 @Override containedType(int index)390 public abstract JavaType containedType(int index); 391 392 @Deprecated // since 2.7 393 @Override containedTypeName(int index)394 public abstract String containedTypeName(int index); 395 396 @Deprecated // since 2.7 397 @Override getParameterSource()398 public Class<?> getParameterSource() { 399 return null; 400 } 401 402 /* 403 /********************************************************** 404 /* Extended API beyond ResolvedType 405 /********************************************************** 406 */ 407 408 // NOTE: not defined in Resolved type 409 /** 410 * Convenience method that is functionally same as: 411 *<code> 412 * JavaType t = containedType(index); 413 * if (t == null) { 414 * t = TypeFactory.unknownType(); 415 * } 416 *</code> 417 * and typically used to eliminate need for null checks for common case 418 * where we just want to check if containedType is available first; and 419 * if not, use "unknown type" (which translates to <code>java.lang.Object</code> 420 * basically). 421 * 422 * @since 2.5 423 */ containedTypeOrUnknown(int index)424 public JavaType containedTypeOrUnknown(int index) { 425 JavaType t = containedType(index); 426 return (t == null) ? TypeFactory.unknownType() : t; 427 } 428 429 /** 430 * @since 2.7 431 */ getBindings()432 public abstract TypeBindings getBindings(); 433 434 /** 435 * Method that may be called to find representation of given type 436 * within type hierarchy of this type: either this type (if this 437 * type has given erased type), one of its supertypes that has the 438 * erased types, or null if target is neither this type or any of its 439 * supertypes. 440 * 441 * @since 2.7 442 */ findSuperType(Class<?> erasedTarget)443 public abstract JavaType findSuperType(Class<?> erasedTarget); 444 445 /** 446 * Accessor for finding fully resolved parent class of this type, 447 * if it has one; null if not. 448 * 449 * @since 2.7 450 */ getSuperClass()451 public abstract JavaType getSuperClass(); 452 453 /** 454 * Accessor for finding fully resolved interfaces this type implements, 455 * if any; empty array if none. 456 * 457 * @since 2.7 458 */ getInterfaces()459 public abstract List<JavaType> getInterfaces(); 460 461 /** 462 * Method that may be used to find paramaterization this type has for 463 * given type-erased generic target type. 464 * 465 * @since 2.7 466 */ findTypeParameters(Class<?> expType)467 public abstract JavaType[] findTypeParameters(Class<?> expType); 468 469 /* 470 /********************************************************** 471 /* Semi-public API, accessing handlers 472 /********************************************************** 473 */ 474 475 /** 476 * Method for accessing value handler associated with this type, if any 477 */ 478 @SuppressWarnings("unchecked") getValueHandler()479 public <T> T getValueHandler() { return (T) _valueHandler; } 480 481 /** 482 * Method for accessing type handler associated with this type, if any 483 */ 484 @SuppressWarnings("unchecked") getTypeHandler()485 public <T> T getTypeHandler() { return (T) _typeHandler; } 486 487 /** 488 * @since 2.7 489 */ getContentValueHandler()490 public Object getContentValueHandler() { return null; } 491 492 /** 493 * @since 2.7 494 */ getContentTypeHandler()495 public Object getContentTypeHandler() { return null; } 496 497 /** 498 * @since 2.6 499 */ hasValueHandler()500 public boolean hasValueHandler() { return _valueHandler != null; } 501 502 /** 503 * Helper method that checks whether this type, or its (optional) key 504 * or content type has {@link #getValueHandler} or {@link #getTypeHandler()}; 505 * that is, are there any non-standard handlers associated with this 506 * type object. 507 * 508 * @since 2.8 509 */ hasHandlers()510 public boolean hasHandlers() { 511 return (_typeHandler != null) || (_valueHandler != null); 512 } 513 514 /* 515 /********************************************************** 516 /* Support for producing signatures 517 /********************************************************** 518 */ 519 520 //public abstract String toCanonical(); 521 522 /** 523 * Method for accessing signature that contains generic 524 * type information, in form compatible with JVM 1.5 525 * as per JLS. It is a superset of {@link #getErasedSignature}, 526 * in that generic information can be automatically removed 527 * if necessary (just remove outermost 528 * angle brackets along with content inside) 529 */ getGenericSignature()530 public String getGenericSignature() { 531 StringBuilder sb = new StringBuilder(40); 532 getGenericSignature(sb); 533 return sb.toString(); 534 } 535 536 /** 537 * 538 * @param sb StringBuilder to append signature to 539 * 540 * @return StringBuilder that was passed in; returned to allow 541 * call chaining 542 */ getGenericSignature(StringBuilder sb)543 public abstract StringBuilder getGenericSignature(StringBuilder sb); 544 545 /** 546 * Method for accessing signature without generic 547 * type information, in form compatible with all versions 548 * of JVM, and specifically used for type descriptions 549 * when generating byte code. 550 */ getErasedSignature()551 public String getErasedSignature() { 552 StringBuilder sb = new StringBuilder(40); 553 getErasedSignature(sb); 554 return sb.toString(); 555 } 556 557 /** 558 * Method for accessing signature without generic 559 * type information, in form compatible with all versions 560 * of JVM, and specifically used for type descriptions 561 * when generating byte code. 562 * 563 * @param sb StringBuilder to append signature to 564 * 565 * @return StringBuilder that was passed in; returned to allow 566 * call chaining 567 */ getErasedSignature(StringBuilder sb)568 public abstract StringBuilder getErasedSignature(StringBuilder sb); 569 570 /* 571 /********************************************************** 572 /* Standard methods; let's make them abstract to force override 573 /********************************************************** 574 */ 575 576 @Override toString()577 public abstract String toString(); 578 579 @Override equals(Object o)580 public abstract boolean equals(Object o); 581 582 @Override hashCode()583 public final int hashCode() { return _hash; } 584 } 585