diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleCallbackFactory.java b/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleCallbackFactory.java index b5f31160e..6cad83b86 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleCallbackFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/LifecycleCallbackFactory.java @@ -106,11 +106,17 @@ public final class LifecycleCallbackFactory { MethodSelectors selectors = new MethodSelectors( ctx.getTypeUtils(), ctx.getElementUtils(), ctx.getTypeFactory() ); + Type targetType = method.getResultType(); + + if ( !method.isUpdateMethod() ) { + targetType = targetType.getEffectiveType(); + } + List> matchingMethods = selectors.getMatchingMethods( method, callbackMethods, Collections. emptyList(), - method.getResultType(), + targetType, SelectionCriteria.forLifecycleMethods( selectionParameters ) ); return toLifecycleCallbackMethodRefs( 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 81e475deb..6bba770a7 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,8 +21,12 @@ --> <#if overridden>@Override <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, )<@throws/> { + <#assign targetType = resultType /> + <#if !existingInstanceMapping> + <#assign targetType = resultType.effectiveType /> + <#list beforeMappingReferencesWithoutMappingTarget as callback> - <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + <@includeModel object=callback targetBeanName=resultName targetType=targetType/> <#if !callback_has_next> @@ -38,7 +42,7 @@ <#list beforeMappingReferencesWithMappingTarget as callback> - <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + <@includeModel object=callback targetBeanName=resultName targetType=targetType/> <#if !callback_has_next> @@ -74,7 +78,7 @@ <#if callback_index = 0> - <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + <@includeModel object=callback targetBeanName=resultName targetType=targetType/> <#if returnType.name != "void"> 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 new file mode 100644 index 000000000..9ef7b2469 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/BuilderLifecycleCallbacksTest.java @@ -0,0 +1,67 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Filip Hrisafov + */ +@RunWith( AnnotationProcessorTestRunner.class ) +@IssueKey( "1433" ) +@WithClasses( { + Item.class, + ItemDto.class, + MappingContext.class, + Order.class, + OrderDto.class, + OrderMapper.class +} ) +public class BuilderLifecycleCallbacksTest { + + @Test + public void lifecycleMethodsShouldBeInvoked() { + OrderDto source = new OrderDto(); + source.setCreator( "Filip" ); + ItemDto item1 = new ItemDto(); + item1.setName( "Laptop" ); + ItemDto item2 = new ItemDto(); + item2.setName( "Keyboard" ); + source.setItems( Arrays.asList( item1, item2 ) ); + MappingContext context = new MappingContext(); + + OrderMapper.INSTANCE.map( source, context ); + + assertThat( context.getInvokedMethods() ) + .contains( + "beforeWithBuilderTargetType", + "beforeWithBuilderTarget", + "afterWithBuilderTargetType", + "afterWithBuilderTarget" + ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Item.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Item.java new file mode 100644 index 000000000..636a71b0e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Item.java @@ -0,0 +1,52 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +/** + * @author Filip Hrisafov + */ +public class Item { + + private final String name; + + Item(Builder builder) { + this.name = builder.name; + } + + public String getName() { + return name; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + + public Builder name(String name) { + this.name = name; + return this; + } + + public Item create() { + return new Item( this ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/ItemDto.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/ItemDto.java new file mode 100644 index 000000000..a14d93265 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/ItemDto.java @@ -0,0 +1,35 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +/** + * @author Filip Hrisafov + */ +public class ItemDto { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} 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 new file mode 100644 index 000000000..5b4f6487f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/MappingContext.java @@ -0,0 +1,79 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +import java.util.ArrayList; +import java.util.List; + +import org.mapstruct.AfterMapping; +import org.mapstruct.BeforeMapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.TargetType; + +/** + * @author Filip Hrisafov + */ +public class MappingContext { + + private final List invokedMethods = new ArrayList(); + + @BeforeMapping + public void beforeWithTargetType(OrderDto source, @TargetType Class orderClass) { + invokedMethods.add( "beforeWithTargetType" ); + } + + @BeforeMapping + public void beforeWithBuilderTargetType(OrderDto source, @TargetType Class builderClass) { + invokedMethods.add( "beforeWithBuilderTargetType" ); + } + + @BeforeMapping + public void beforeWithTarget(OrderDto source, @MappingTarget Order order) { + invokedMethods.add( "beforeWithTarget" ); + } + + @BeforeMapping + public void beforeWithBuilderTarget(OrderDto source, @MappingTarget Order.Builder orderBuilder) { + invokedMethods.add( "beforeWithBuilderTarget" ); + } + + @AfterMapping + public void afterWithTargetType(OrderDto source, @TargetType Class orderClass) { + invokedMethods.add( "afterWithTargetType" ); + } + + @AfterMapping + public void afterWithBuilderTargetType(OrderDto source, @TargetType Class builderClass) { + invokedMethods.add( "afterWithBuilderTargetType" ); + } + + @AfterMapping + public void afterWithTarget(OrderDto source, @MappingTarget Order order) { + invokedMethods.add( "afterWithTarget" ); + } + + @AfterMapping + public void afterWithBuilderTarget(OrderDto source, @MappingTarget Order.Builder orderBuilder) { + invokedMethods.add( "afterWithBuilderTarget" ); + } + + public List getInvokedMethods() { + return invokedMethods; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Order.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Order.java new file mode 100644 index 000000000..b3d1d3621 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/Order.java @@ -0,0 +1,62 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Filip Hrisafov + */ +public class Order { + + private final List items; + private final String creator; + + public Order(Builder builder) { + this.items = new ArrayList( builder.items ); + this.creator = builder.creator; + } + + public List getItems() { + return items; + } + + public String getCreator() { + return creator; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private List items = new ArrayList(); + private String creator; + + public Builder items(List items) { + this.items = items; + return this; + } + + public Order create() { + return new Order( this ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderDto.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderDto.java new file mode 100644 index 000000000..958a668c0 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderDto.java @@ -0,0 +1,46 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +import java.util.List; + +/** + * @author Filip Hrisafov + */ +public class OrderDto { + + private List items; + private String creator; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public String getCreator() { + return creator; + } + + public void setCreator(String creator) { + this.creator = creator; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderMapper.java b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderMapper.java new file mode 100644 index 000000000..ccfcb4290 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/builder/lifecycle/OrderMapper.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.builder.lifecycle; + +import org.mapstruct.Context; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * @author Filip Hrisafov + */ +@Mapper +public interface OrderMapper { + + OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class ); + + Order map(OrderDto source, @Context MappingContext context); + + Item map(ItemDto source, @Context MappingContext context); +}