diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 459a4f82d..3c3e62a94 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -262,10 +262,10 @@ public class BeanMappingMethod extends NormalTypeMappingMethod { return null; } - if ( !mappingReferences.isRestrictToDefinedMappings() ) { + // apply name based mapping from a source reference + applyTargetThisMapping(); - // apply name based mapping from a source reference - applyTargetThisMapping(); + if ( !mappingReferences.isRestrictToDefinedMappings() ) { // map properties without a mapping applyPropertyNameBasedMapping(); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java index 254ba6287..cd5f0efd2 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedTargetPropertyMappingHolder.java @@ -230,7 +230,11 @@ public class NestedTargetPropertyMappingHolder { // do update on the defined Mappings. if ( !groupedSourceReferences.nonNested.isEmpty() ) { MappingReferences mappingReferences = - new MappingReferences( groupedSourceReferences.nonNested, true ); + new MappingReferences( + groupedSourceReferences.nonNested.references, + groupedSourceReferences.nonNested.getTargetThisReferences(), + true + ); SourceReference reference = new SourceReference.BuilderFromProperty() .sourceParameter( sourceParameter ) .name( targetProperty ) @@ -361,8 +365,19 @@ public class NestedTargetPropertyMappingHolder { Map> singleTargetReferences = new LinkedHashMap<>(); for ( MappingReference mapping : mappingReferences.getMappingReferences() ) { TargetReference targetReference = mapping.getTargetReference(); + SourceReference sourceReference = mapping.getSourceReference(); String property = first( targetReference.getPropertyEntries() ); MappingReference newMapping = mapping.popTargetReference(); + + if ( newMapping == null && method.getSourceParameters().size() == 1 && sourceReference != null && sourceReference.getParameter() != null && + sourceReference.getPropertyEntries().isEmpty() && + !targetReference.getPropertyEntries().isEmpty() ) { + List newPathProperties = new ArrayList<>( targetReference.getPathProperties() ); + newPathProperties.add( targetReference.getPropertyEntries().get( 0 ) ); + TargetReference newTargetReference = new TargetReference( null, Collections.singletonList( "." ), newPathProperties); + newMapping = new MappingReference( mapping.getMapping(), newTargetReference, sourceReference ); + } + if ( newMapping != null ) { // group properties on current name. mappingsKeyedByProperty.computeIfAbsent( property, propertyEntry -> new LinkedHashSet<>() ) @@ -526,7 +541,7 @@ public class NestedTargetPropertyMappingHolder { Map.Entry> entryByParam, Set singleTargetReferences) { Set mappings = entryByParam.getValue(); - Set nonNested = new LinkedHashSet<>(); + NestedReferences nonNested = new NestedReferences(); Set appliesToAll = new LinkedHashSet<>(); Set sourceParameterMappings = new LinkedHashSet<>(); // group all mappings based on the top level name before popping @@ -780,12 +795,12 @@ public class NestedTargetPropertyMappingHolder { private static class GroupedSourceReferences { private final Map> groupedBySourceReferences; - private final Set nonNested; + private final NestedReferences nonNested; private final Set notProcessedAppliesToAll; private final Set sourceParameterMappings; private GroupedSourceReferences(Map> groupedBySourceReferences, - Set nonNested, Set notProcessedAppliesToAll, + NestedReferences nonNested, Set notProcessedAppliesToAll, Set sourceParameterMappings) { this.groupedBySourceReferences = groupedBySourceReferences; this.nonNested = nonNested; @@ -801,4 +816,37 @@ public class NestedTargetPropertyMappingHolder { + ", sourceParameterMappings=" + sourceParameterMappings + '}'; } } + + private static class NestedReferences { + + private final Set references = new LinkedHashSet<>(); + private List targetThisReferences; + + public void add(MappingReference mapping) { + TargetReference targetReference = mapping.getTargetReference(); + if ( targetReference != null && targetReference.getPropertyEntries().size() == 1 && + ".".equals( targetReference.getShallowestPropertyName() ) ) { + if ( targetThisReferences == null ) { + targetThisReferences = new ArrayList<>(); + } + targetThisReferences.add( mapping ); + } + else { + references.add( mapping ); + } + } + + public void addAll(Set mappingReferences) { + mappingReferences.forEach( this::add ); + } + + public boolean isEmpty() { + return references.isEmpty() && (targetThisReferences == null || targetThisReferences.isEmpty()); + } + + public List getTargetThisReferences() { + return targetThisReferences != null ? targetThisReferences : Collections.emptyList(); + } + + } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java index 1d747c190..a0ac7297f 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/beanmapping/SourceReference.java @@ -418,11 +418,25 @@ public class SourceReference extends AbstractReference { public List push(TypeFactory typeFactory, FormattingMessager messager, Method method ) { List result = new ArrayList<>(); PropertyEntry deepestProperty = getDeepestProperty(); + String fullName; + Type type; if ( deepestProperty != null ) { - Type type = deepestProperty.getType(); + fullName = deepestProperty.getFullName(); + type = deepestProperty.getType(); + } + else if ( getParameter() != null ) { + fullName = getParameter().getName(); + type = getParameter().getType(); + } + else { + fullName = null; + type = null; + } + + if ( type != null ) { Map newDeepestReadAccessors = type.getPropertyReadAccessors(); for ( Map.Entry newDeepestReadAccessorEntry : newDeepestReadAccessors.entrySet() ) { - String newFullName = deepestProperty.getFullName() + "." + newDeepestReadAccessorEntry.getKey(); + String newFullName = fullName + "." + newDeepestReadAccessorEntry.getKey(); SourceReference sourceReference = new BuilderFromMapping() .sourceName( newFullName ) .method( method )