@@ -339,4 +339,195 @@ public abstract static class None {}
339339 * @since 2.16
340340 */
341341 public OptBoolean requireTypeIdForSubtypes () default OptBoolean .DEFAULT ;
342+
343+ /*
344+ /**********************************************************************
345+ /* Value class used to enclose information, allow for
346+ /* merging of layered configuration settings.
347+ /**********************************************************************
348+ */
349+
350+ public static class Value
351+ implements JacksonAnnotationValue <JsonTypeInfo >,
352+ java .io .Serializable
353+ {
354+ private static final long serialVersionUID = 1L ;
355+
356+ // should not really be needed usually but make sure defalts to `NONE`; other
357+ // values of less interest
358+ protected final static Value EMPTY = new Value (Id .NONE , As .PROPERTY , null , null , false , null );
359+
360+ protected final Id _idType ;
361+ protected final As _inclusionType ;
362+ protected final String _propertyName ;
363+
364+ protected final Class <?> _defaultImpl ;
365+ protected final boolean _idVisible ;
366+ protected final Boolean _requireTypeIdForSubtypes ;
367+
368+ /*
369+ /**********************************************************************
370+ /* Construction
371+ /**********************************************************************
372+ */
373+
374+ protected Value (Id idType , As inclusionType ,
375+ String propertyName , Class <?> defaultImpl , boolean idVisible , Boolean requireTypeIdForSubtypes )
376+ {
377+ _defaultImpl = defaultImpl ;
378+ _idType = idType ;
379+ _inclusionType = inclusionType ;
380+ _propertyName = propertyName ;
381+ _idVisible = idVisible ;
382+ _requireTypeIdForSubtypes = requireTypeIdForSubtypes ;
383+ }
384+
385+ public static Value construct (Id idType , As inclusionType ,
386+ String propertyName , Class <?> defaultImpl , boolean idVisible , Boolean requireTypeIdForSubtypes )
387+ {
388+ // couple of overrides we need to apply here. First: if no propertyName specified,
389+ // use Id-specific property name
390+ if ((propertyName == null ) || propertyName .isEmpty ()) {
391+ if (idType != null ) {
392+ propertyName = idType .getDefaultPropertyName ();
393+ } else {
394+ propertyName = "" ;
395+ }
396+ }
397+ // Although we can not do much here for special handling of `Void`, we can convert
398+ // annotation types as `null` (== no default implementation)
399+ if ((defaultImpl == null ) || defaultImpl .isAnnotation ()) {
400+ defaultImpl = null ;
401+ }
402+ return new Value (idType , inclusionType , propertyName , defaultImpl , idVisible , requireTypeIdForSubtypes );
403+ }
404+
405+ public static Value from (JsonTypeInfo src ) {
406+ if (src == null ) {
407+ return null ;
408+ }
409+ return construct (src .use (), src .include (),
410+ src .property (), src .defaultImpl (), src .visible (), src .requireTypeIdForSubtypes ().asBoolean ());
411+ }
412+
413+ /*
414+ /**********************************************************************
415+ /* Mutators
416+ /**********************************************************************
417+ */
418+
419+ public Value withDefaultImpl (Class <?> impl ) {
420+ return (impl == _defaultImpl ) ? this :
421+ new Value (_idType , _inclusionType , _propertyName , impl , _idVisible , _requireTypeIdForSubtypes );
422+ }
423+
424+ public Value withIdType (Id idType ) {
425+ return (idType == _idType ) ? this :
426+ new Value (idType , _inclusionType , _propertyName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
427+ }
428+
429+ public Value withInclusionType (As inclusionType ) {
430+ return (inclusionType == _inclusionType ) ? this :
431+ new Value (_idType , inclusionType , _propertyName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
432+ }
433+
434+ public Value withPropertyName (String propName ) {
435+ return (propName == _propertyName ) ? this :
436+ new Value (_idType , _inclusionType , propName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
437+ }
438+
439+ public Value withIdVisible (boolean visible ) {
440+ return (visible == _idVisible ) ? this :
441+ new Value (_idType , _inclusionType , _propertyName , _defaultImpl , visible , _requireTypeIdForSubtypes );
442+ }
443+
444+ public Value withRequireTypeIdForSubtypes (Boolean requireTypeIdForSubtypes ) {
445+ return (_requireTypeIdForSubtypes == requireTypeIdForSubtypes ) ? this :
446+ new Value (_idType , _inclusionType , _propertyName , _defaultImpl , _idVisible , requireTypeIdForSubtypes );
447+ }
448+
449+ /*
450+ /**********************************************************************
451+ /* Simple accessors
452+ /**********************************************************************
453+ */
454+
455+ @ Override
456+ public Class <JsonTypeInfo > valueFor () {
457+ return JsonTypeInfo .class ;
458+ }
459+
460+ public Class <?> getDefaultImpl () { return _defaultImpl ; }
461+ public Id getIdType () { return _idType ; }
462+ public As getInclusionType () { return _inclusionType ; }
463+ public String getPropertyName () { return _propertyName ; }
464+ public boolean getIdVisible () { return _idVisible ; }
465+ public Boolean getRequireTypeIdForSubtypes () { return _requireTypeIdForSubtypes ; }
466+
467+ /**
468+ * Static helper method for simple(r) checking of whether there's a Value instance
469+ * that indicates that polymorphic handling is (to be) enabled.
470+ */
471+ public static boolean isEnabled (JsonTypeInfo .Value v ) {
472+ return (v != null ) &&
473+ (v ._idType != null ) && (v ._idType != Id .NONE );
474+ }
475+
476+ /*
477+ /**********************************************************************
478+ /* Standard methods
479+ /**********************************************************************
480+ */
481+
482+ @ Override
483+ public String toString () {
484+ return String .format ("JsonTypeInfo.Value(idType=%s,includeAs=%s,propertyName=%s,defaultImpl=%s,idVisible=%s"
485+ + ",requireTypeIdForSubtypes=%s)" ,
486+ _idType , _inclusionType , _propertyName ,
487+ ((_defaultImpl == null ) ? "NULL" : _defaultImpl .getName ()),
488+ _idVisible , _requireTypeIdForSubtypes );
489+ }
490+
491+ @ Override
492+ public int hashCode () {
493+ int hashCode = 1 ;
494+ hashCode = 31 * hashCode + (_idType != null ? _idType .hashCode () : 0 );
495+ hashCode = 31 * hashCode + (_inclusionType != null ? _inclusionType .hashCode () : 0 );
496+ hashCode = 31 * hashCode + (_propertyName != null ? _propertyName .hashCode () : 0 );
497+ hashCode = 31 * hashCode + (_defaultImpl != null ? _defaultImpl .hashCode () : 0 );
498+ hashCode = 31 * hashCode + (_requireTypeIdForSubtypes ? 11 : -17 );
499+ hashCode = 31 * hashCode + (_idVisible ? 11 : -17 );
500+ return hashCode ;
501+ }
502+
503+ @ Override
504+ public boolean equals (Object o ) {
505+ if (o == this ) return true ;
506+ if (o == null ) return false ;
507+ return (o .getClass () == getClass ())
508+ && _equals (this , (Value ) o );
509+ }
510+
511+ private static boolean _equals (Value a , Value b )
512+ {
513+ return (a ._idType == b ._idType )
514+ && (a ._inclusionType == b ._inclusionType )
515+ && (a ._defaultImpl == b ._defaultImpl )
516+ && (a ._idVisible == b ._idVisible )
517+ && _equal (a ._propertyName , b ._propertyName )
518+ && _equal (a ._requireTypeIdForSubtypes , b ._requireTypeIdForSubtypes )
519+ ;
520+ }
521+
522+ private static <T > boolean _equal (T value1 , T value2 )
523+ {
524+ if (value1 == null ) {
525+ return (value2 == null );
526+ }
527+ if (value2 == null ) {
528+ return false ;
529+ }
530+ return value1 .equals (value2 );
531+ }
532+ }
342533}
0 commit comments