> matchingFactoryMethods =
@@ -1380,7 +1415,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
*
* When a target property matches its name with the (nested) source property, it is added to the list if and
* only if it is an unprocessed target property.
- *
+ *
* duplicates will be handled by {@link #applyPropertyNameBasedMapping(List)}
*/
private void applyTargetThisMapping() {
@@ -1766,6 +1801,8 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
BuilderType returnTypeBuilder,
List beforeMappingReferences,
List afterMappingReferences,
+ List beforeMappingReferencesWithFinalizedReturnType,
+ List afterMappingReferencesWithFinalizedReturnType,
MethodReference finalizerMethod,
MappingReferences mappingReferences,
List subclassMappings) {
@@ -1783,9 +1820,20 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
this.propertyMappings = propertyMappings;
this.returnTypeBuilder = returnTypeBuilder;
this.finalizerMethod = finalizerMethod;
+ if ( this.finalizerMethod != null ) {
+ this.finalizedResultName =
+ Strings.getSafeVariableName( getResultName() + "Result", existingVariableNames );
+ existingVariableNames.add( this.finalizedResultName );
+ }
+ else {
+ this.finalizedResultName = null;
+ }
this.mappingReferences = mappingReferences;
- // intialize constant mappings as all mappings, but take out the ones that can be contributed to a
+ this.beforeMappingReferencesWithFinalizedReturnType = beforeMappingReferencesWithFinalizedReturnType;
+ this.afterMappingReferencesWithFinalizedReturnType = afterMappingReferencesWithFinalizedReturnType;
+
+ // initialize constant mappings as all mappings, but take out the ones that can be contributed to a
// parameter mapping.
this.mappingsByParameter = new HashMap<>();
this.constantMappings = new ArrayList<>( propertyMappings.size() );
@@ -1830,6 +1878,18 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
return subclassMappings;
}
+ public String getFinalizedResultName() {
+ return finalizedResultName;
+ }
+
+ public List getBeforeMappingReferencesWithFinalizedReturnType() {
+ return beforeMappingReferencesWithFinalizedReturnType;
+ }
+
+ public List getAfterMappingReferencesWithFinalizedReturnType() {
+ return afterMappingReferencesWithFinalizedReturnType;
+ }
+
public List propertyMappingsByParameter(Parameter parameter) {
// issues: #909 and #1244. FreeMarker has problem getting values from a map when the search key is size or value
return mappingsByParameter.getOrDefault( parameter.getName(), Collections.emptyList() );
@@ -1882,6 +1942,12 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
if ( returnTypeBuilder != null ) {
types.add( returnTypeBuilder.getOwningType() );
}
+ for ( LifecycleCallbackMethodReference reference : beforeMappingReferencesWithFinalizedReturnType ) {
+ types.addAll( reference.getImportTypes() );
+ }
+ for ( LifecycleCallbackMethodReference reference : afterMappingReferencesWithFinalizedReturnType ) {
+ types.addAll( reference.getImportTypes() );
+ }
return types;
}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java
index 5b9eda644..4c59216e0 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java
@@ -186,8 +186,8 @@ public abstract class MappingMethod extends ModelElement {
return returnType + " " + getName() + "(" + join( parameters, ", " ) + ")";
}
- private List filterMappingTarget(List methods,
- boolean mustHaveMappingTargetParameter) {
+ protected static List filterMappingTarget(
+ List methods, boolean mustHaveMappingTargetParameter) {
if ( methods == null ) {
return Collections.emptyList();
}
diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
index 1b402a57f..a0fbe24b3 100644
--- a/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
+++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/BeanMappingMethod.ftl
@@ -21,6 +21,12 @@
#if>
#list>
+ <#list beforeMappingReferencesWithFinalizedReturnType as callback>
+ <@includeModel object=callback targetBeanName=finalizedResultName targetType=returnType/>
+ <#if !callback_has_next>
+
+ #if>
+ #list>
<#if !mapNullToDefault>
if ( <#list sourceParametersExcludingPrimitives as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && #if>#list> ) {
return<#if returnType.name != "void"> <#if existingInstanceMapping>${resultName}<#if finalizerMethod??>.<@includeModel object=finalizerMethod />#if><#else>null#if>#if>;
@@ -129,7 +135,20 @@
<#if returnType.name != "void">
<#if finalizerMethod??>
- return ${resultName}.<@includeModel object=finalizerMethod />;
+ <#if (afterMappingReferencesWithFinalizedReturnType?size > 0)>
+ ${returnType.name} ${finalizedResultName} = ${resultName}.<@includeModel object=finalizerMethod />;
+
+ <#list afterMappingReferencesWithFinalizedReturnType as callback>
+ <#if callback_index = 0>
+
+ #if>
+ <@includeModel object=callback targetBeanName=finalizedResultName targetType=returnType/>
+ #list>
+
+ return ${finalizedResultName};
+ <#else>
+ return ${resultName}.<@includeModel object=finalizerMethod />;
+ #if>
<#else>
return ${resultName};
#if>
diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/BuilderLifecycleCallbacksTest.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/BuilderLifecycleCallbacksTest.java
index e3892f215..3d5fb7e53 100644
--- a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/BuilderLifecycleCallbacksTest.java
+++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/BuilderLifecycleCallbacksTest.java
@@ -43,12 +43,16 @@ public class BuilderLifecycleCallbacksTest {
assertThat( context.getInvokedMethods() )
.contains(
"beforeWithoutParameters",
+ "beforeWithTargetType",
"beforeWithBuilderTargetType",
"beforeWithBuilderTarget",
"afterWithoutParameters",
"afterWithBuilderTargetType",
"afterWithBuilderTarget",
- "afterWithBuilderTargetReturningTarget"
+ "afterWithBuilderTargetReturningTarget",
+ "afterWithTargetType",
+ "afterWithTarget",
+ "afterWithTargetReturningTarget"
);
}
}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/MappingContext.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/MappingContext.java
index 96b9b30db..079be90a8 100644
--- a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/MappingContext.java
+++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/MappingContext.java
@@ -74,7 +74,15 @@ public class MappingContext {
public Order afterWithBuilderTargetReturningTarget(@MappingTarget Order.Builder orderBuilder) {
invokedMethods.add( "afterWithBuilderTargetReturningTarget" );
- return orderBuilder.create();
+ // return null, so that @AfterMapping methods on the finalized object will be called in the tests
+ return null;
+ }
+
+ @AfterMapping
+ public Order afterWithTargetReturningTarget(@MappingTarget Order order) {
+ invokedMethods.add( "afterWithTargetReturningTarget" );
+
+ return order;
}
public List getInvokedMethods() {