diff --git a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java index 84802965e9..303e0ba0d0 100644 --- a/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java +++ b/src/main/java/com/fasterxml/jackson/databind/BeanDescription.java @@ -14,9 +14,9 @@ /** * Basic container for information gathered by {@link ClassIntrospector} to * help in constructing serializers and deserializers. - * Note that the main implementation type is + * Note that the one implementation type is * {@link com.fasterxml.jackson.databind.introspect.BasicBeanDescription}, - * meaning that it is safe to upcast to this type. + * meaning that it is safe to upcast to that type. */ public abstract class BeanDescription { @@ -109,7 +109,7 @@ public boolean isNonStaticInnerClass() { /* /********************************************************** - /* Basic API for finding creator members + /* Basic API for finding Creators, related information /********************************************************** */ @@ -166,6 +166,15 @@ public boolean isNonStaticInnerClass() { */ public abstract AnnotatedConstructor findDefaultConstructor(); + /** + * Method that is replacing earlier Creator introspection access methods. + * + * @since 2.18 + * + * @return Container for introspected Creator candidates, if any + */ + public abstract PotentialCreators getPotentialCreators(); + /* /********************************************************** /* Basic API for finding property accessors diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java index e6eec6485f..0972bfcbf2 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -623,12 +623,6 @@ protected void _addExplicitFactoryCreators(DeserializationContext ctxt, continue; } - // zero-arg method factory methods fine, as long as explicit - if (argCount == 0) { - creators.setDefaultCreator(factory); - continue; - } - switch (creatorMode) { case DELEGATING: _addExplicitDelegatingCreator(ctxt, beanDesc, creators, @@ -707,34 +701,8 @@ protected void _addImplicitFactoryCreators(DeserializationContext ctxt, NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param); if (unwrapper != null) { _reportUnwrappedCreatorProperty(ctxt, beanDesc, param); - /* - properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null); - ++implicitNameCount; - */ continue; } - // One more thing: implicit names are ok iff ctor has creator annotation - /* - if (isCreator) { - if (name != null && !name.isEmpty()) { - ++implicitNameCount; - properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable); - continue; - } - } - */ - /* 25-Sep-2014, tatu: Actually, we may end up "losing" naming due to higher-priority constructor - * (see TestCreators#testConstructorCreator() test). And just to avoid running into that problem, - * let's add one more work around - */ - /* - PropertyName name2 = _findExplicitParamName(param, intr); - if (name2 != null && !name2.isEmpty()) { - // Hmmh. Ok, fine. So what are we to do with it... ? - // For now... skip. May need to revisit this, should this become problematic - continue main_loop; - } - */ if (nonAnnotatedParam == null) { nonAnnotatedParam = param; } @@ -841,10 +809,6 @@ protected void _addExplicitPropertyCreator(DeserializationContext ctxt, NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(param); if (unwrapper != null) { _reportUnwrappedCreatorProperty(ctxt, beanDesc, param); - /* - properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null); - ++explicitNameCount; - */ } name = candidate.findImplicitParamName(i); _validateNamedPropertyParameter(ctxt, beanDesc, candidate, i, diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java index 63f54879b2..a1d35357d9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicBeanDescription.java @@ -340,6 +340,11 @@ public List> getCon return result; } + @Override + public PotentialCreators getPotentialCreators() { + return _propCollector.getPotentialCreators(); + } + @Override public Object instantiateBean(boolean fixAccess) { AnnotatedConstructor ac = _classInfo.getDefaultConstructor(); diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java index c11e360a33..7037b722b6 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java @@ -91,6 +91,11 @@ public class POJOPropertiesCollector protected List _creatorProperties; + /** + * @since 2.18 + */ + protected PotentialCreators _potentialCreators; + /** * A set of "field renamings" that have been discovered, indicating * intended renaming of other accessors: key is the implicit original @@ -218,6 +223,14 @@ public List getProperties() { return new ArrayList<>(props.values()); } + // @since 2.18 + public PotentialCreators getPotentialCreators() { + if (!_collected) { + collectAll(); + } + return _potentialCreators; + } + public Map getInjectables() { if (!_collected) { collectAll(); @@ -626,6 +639,8 @@ protected void _addFields(Map props) // Completely rewritten in 2.18 protected void _addCreators(Map props) { + final PotentialCreators creators = new PotentialCreators(); + _potentialCreators = creators; _creatorProperties = new ArrayList<>(); // First, resolve explicit annotations for all potential Creators @@ -648,35 +663,35 @@ protected void _addCreators(Map props) _removeDisabledCreators(constructors); _removeDisabledCreators(factories); - final PotentialCreators collector = new PotentialCreators(); // and use annotations to find explicitly chosen Creators if (_useAnnotations) { // can't have explicit ones without Annotation introspection // Start with Constructors as they have higher precedence: - _addExplicitlyAnnotatedCreators(collector, constructors, props, false); + _addExplicitlyAnnotatedCreators(creators, constructors, props, false); // followed by Factory methods (lower precedence) - _addExplicitlyAnnotatedCreators(collector, factories, props, - collector.hasPropertiesBased()); + _addExplicitlyAnnotatedCreators(creators, factories, props, + creators.hasPropertiesBased()); } // If no Explicitly annotated creators found, look // for ones with explicitly-named ({@code @JsonProperty}) parameters - if (!collector.hasPropertiesBased()) { + if (!creators.hasPropertiesBased()) { // only discover constructor Creators? - _addCreatorsWithAnnotatedNames(collector, constructors); + _addCreatorsWithAnnotatedNames(creators, constructors); } // But if no annotation-based Creators found, find/use canonical Creator // (JDK 17 Record/Scala/Kotlin) - if (!collector.hasPropertiesBased()) { + if (!creators.hasPropertiesBased()) { // for Records: if ((canonical != null) && constructors.contains(canonical)) { constructors.remove(canonical); - collector.addPropertiesBased(_config, canonical, "canonical"); + creators.setPropertiesBased(_config, canonical, "canonical"); } } - // And finally add logical properties: - PotentialCreator primary = collector.propertiesBased; + // And finally add logical properties for the One Properties-based + // creator selected (if any): + PotentialCreator primary = creators.propertiesBased; if (primary != null) { _addCreatorParams(props, primary); } @@ -766,10 +781,10 @@ private void _addExplicitlyAnnotatedCreators(PotentialCreators collector, if (propsBased) { // Skipping done if we already got higher-precedence Creator if (!skipPropsBased) { - collector.addPropertiesBased(_config, ctor, "explicit"); + collector.setPropertiesBased(_config, ctor, "explicit"); } } else { - collector.addDelegating(ctor); + collector.addExplicitDelegating(ctor); } } } @@ -788,7 +803,7 @@ private void _addCreatorsWithAnnotatedNames(PotentialCreators collector, } it.remove(); - collector.addPropertiesBased(_config, ctor, "implicit"); + collector.setPropertiesBased(_config, ctor, "implicit"); } } diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreator.java b/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreator.java index f46e7b7734..7d2a1b3730 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreator.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreator.java @@ -152,6 +152,10 @@ public String implicitNameSimple(int ix) { return (pn == null) ? null : pn.getSimpleName(); } + public BeanPropertyDefinition[] propertyDefs() { + return propertyDefs; + } + /* /********************************************************************** /* Misc other diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreators.java b/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreators.java index 5a3ad070a4..077a8b86fc 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreators.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/PotentialCreators.java @@ -11,7 +11,10 @@ public class PotentialCreators */ public PotentialCreator propertiesBased; - public final List delegating = new ArrayList<>(); + private List explicitDelegating; + + private List implicitDelegatingConstructors; + private List implicitDelegatingFactories; public PotentialCreators() { @@ -24,7 +27,7 @@ public PotentialCreators() */ // desc -> "explicit", "implicit" etc - public void addPropertiesBased(MapperConfig config, PotentialCreator ctor, String mode) + public void setPropertiesBased(MapperConfig config, PotentialCreator ctor, String mode) { if (propertiesBased != null) { throw new IllegalArgumentException(String.format( @@ -34,9 +37,19 @@ public void addPropertiesBased(MapperConfig config, PotentialCreator ctor, St propertiesBased = ctor.introspectParamNames(config); } - public void addDelegating(PotentialCreator ctor) + public void addExplicitDelegating(PotentialCreator ctor) + { + if (explicitDelegating == null) { + explicitDelegating = new ArrayList<>(); + } + explicitDelegating.add(ctor); + } + + public void setImplicitDelegating(List implicitConstructors, + List implicitFactories) { - delegating.add(ctor); + implicitDelegatingConstructors = implicitConstructors; + implicitDelegatingFactories = implicitFactories; } /* @@ -50,6 +63,18 @@ public boolean hasPropertiesBased() { } public boolean hasPropertiesBasedOrDelegating() { - return (propertiesBased != null) || !delegating.isEmpty(); + return (propertiesBased != null) || (explicitDelegating != null && !explicitDelegating.isEmpty()); + } + + public List getExplicitDelegating() { + return (explicitDelegating == null) ? Collections.emptyList() : explicitDelegating; + } + + public List getImplicitDelegatingFactories() { + return implicitDelegatingFactories; + } + + public List getImplicitDelegatingConstructors() { + return implicitDelegatingConstructors; } }