Skip to content

Commit

Permalink
More work on #4515: start refactoring BasicDeserializerFactory (#4539)
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder authored May 22, 2024
1 parent c2be01a commit bc7667d
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 57 deletions.
15 changes: 12 additions & 3 deletions src/main/java/com/fasterxml/jackson/databind/BeanDescription.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -109,7 +109,7 @@ public boolean isNonStaticInnerClass() {

/*
/**********************************************************
/* Basic API for finding creator members
/* Basic API for finding Creators, related information
/**********************************************************
*/

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,11 @@ public List<AnnotatedAndMetadata<AnnotatedConstructor, JsonCreator.Mode>> getCon
return result;
}

@Override
public PotentialCreators getPotentialCreators() {
return _propCollector.getPotentialCreators();
}

@Override
public Object instantiateBean(boolean fixAccess) {
AnnotatedConstructor ac = _classInfo.getDefaultConstructor();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public class POJOPropertiesCollector

protected List<POJOPropertyBuilder> _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
Expand Down Expand Up @@ -218,6 +223,14 @@ public List<BeanPropertyDefinition> getProperties() {
return new ArrayList<>(props.values());
}

// @since 2.18
public PotentialCreators getPotentialCreators() {
if (!_collected) {
collectAll();
}
return _potentialCreators;
}

public Map<Object, AnnotatedMember> getInjectables() {
if (!_collected) {
collectAll();
Expand Down Expand Up @@ -626,6 +639,8 @@ protected void _addFields(Map<String, POJOPropertyBuilder> props)
// Completely rewritten in 2.18
protected void _addCreators(Map<String, POJOPropertyBuilder> props)
{
final PotentialCreators creators = new PotentialCreators();
_potentialCreators = creators;
_creatorProperties = new ArrayList<>();

// First, resolve explicit annotations for all potential Creators
Expand All @@ -648,35 +663,35 @@ protected void _addCreators(Map<String, POJOPropertyBuilder> 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);
}
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -788,7 +803,7 @@ private void _addCreatorsWithAnnotatedNames(PotentialCreators collector,
}
it.remove();

collector.addPropertiesBased(_config, ctor, "implicit");
collector.setPropertiesBased(_config, ctor, "implicit");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ public String implicitNameSimple(int ix) {
return (pn == null) ? null : pn.getSimpleName();
}

public BeanPropertyDefinition[] propertyDefs() {
return propertyDefs;
}

/*
/**********************************************************************
/* Misc other
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ public class PotentialCreators
*/
public PotentialCreator propertiesBased;

public final List<PotentialCreator> delegating = new ArrayList<>();
private List<PotentialCreator> explicitDelegating;

private List<PotentialCreator> implicitDelegatingConstructors;
private List<PotentialCreator> implicitDelegatingFactories;

public PotentialCreators()
{
Expand All @@ -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(
Expand All @@ -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<PotentialCreator> implicitConstructors,
List<PotentialCreator> implicitFactories)
{
delegating.add(ctor);
implicitDelegatingConstructors = implicitConstructors;
implicitDelegatingFactories = implicitFactories;
}

/*
Expand All @@ -50,6 +63,18 @@ public boolean hasPropertiesBased() {
}

public boolean hasPropertiesBasedOrDelegating() {
return (propertiesBased != null) || !delegating.isEmpty();
return (propertiesBased != null) || (explicitDelegating != null && !explicitDelegating.isEmpty());
}

public List<PotentialCreator> getExplicitDelegating() {
return (explicitDelegating == null) ? Collections.emptyList() : explicitDelegating;
}

public List<PotentialCreator> getImplicitDelegatingFactories() {
return implicitDelegatingFactories;
}

public List<PotentialCreator> getImplicitDelegatingConstructors() {
return implicitDelegatingConstructors;
}
}

0 comments on commit bc7667d

Please sign in to comment.