diff --git a/processor/src/main/java/org/mapstruct/ap/model/EnumMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/EnumMappingMethod.java index 898edc36d..68e48d430 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/EnumMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/EnumMappingMethod.java @@ -21,11 +21,14 @@ package org.mapstruct.ap.model; import java.util.ArrayList; import java.util.List; +import javax.lang.model.type.TypeMirror; + import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.source.EnumMapping; import org.mapstruct.ap.model.source.Mapping; import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.SourceMethod; +import org.mapstruct.ap.prism.BeanMappingPrism; import org.mapstruct.ap.util.Message; import org.mapstruct.ap.util.Strings; @@ -93,7 +96,24 @@ public class EnumMappingMethod extends MappingMethod { } } - return new EnumMappingMethod( method, enumMappings ); + List qualifiers = getQualifiers( method ); + + List beforeMappingMethods = + LifecycleCallbackFactory.beforeMappingMethods( method, qualifiers, ctx ); + List afterMappingMethods = + LifecycleCallbackFactory.afterMappingMethods( method, qualifiers, ctx ); + + return new EnumMappingMethod( method, enumMappings, beforeMappingMethods, afterMappingMethods ); + } + + private static List getQualifiers(SourceMethod method) { + BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() ); + + if ( beanMappingPrism != null ) { + return beanMappingPrism.qualifiedBy(); + } + + return null; } private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) { @@ -171,8 +191,10 @@ public class EnumMappingMethod extends MappingMethod { } - private EnumMappingMethod(Method method, List enumMappings) { - super( method ); + private EnumMappingMethod(Method method, List enumMappings, + List beforeMappingMethods, + List afterMappingMethods) { + super( method, beforeMappingMethods, afterMappingMethods ); this.enumMappings = enumMappings; } diff --git a/processor/src/main/resources/org.mapstruct.ap.model.EnumMappingMethod.ftl b/processor/src/main/resources/org.mapstruct.ap.model.EnumMappingMethod.ftl index 8edf9743f..b3ca32173 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.EnumMappingMethod.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.EnumMappingMethod.ftl @@ -20,6 +20,12 @@ --> @Override public <@includeModel object=returnType/> ${name}(<@includeModel object=sourceParameter/>) { + <#list beforeMappingReferencesWithoutMappingTarget as callback> + <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + <#if !callback_has_next> + + + if ( ${sourceParameter.name} == null ) { return null; } @@ -33,6 +39,18 @@ public <@includeModel object=returnType/> ${name}(<@includeModel object=sourcePa default: throw new IllegalArgumentException( "Unexpected enum constant: " + ${sourceParameter.name} ); } + <#list beforeMappingReferencesWithMappingTarget as callback> + <#if callback_index = 0> + + + <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + + <#list afterMappingReferences as callback> + <#if callback_index = 0> + + + <@includeModel object=callback targetBeanName=resultName targetType=resultType/> + return ${resultName}; } \ No newline at end of file diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/BaseMapper.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/BaseMapper.java index 52742d4db..5e750eabb 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/callbacks/BaseMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/BaseMapper.java @@ -52,6 +52,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); } + @BeforeMapping + public void withSourceBeforeMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + @BeforeMapping public void withSourceBeforeMapping(List source) { INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); @@ -84,6 +89,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); } + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(SourceEnum source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + @BeforeMapping public void withSourceAndTargetTypeBeforeMapping(List source, @TargetType Class targetClass) { INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); @@ -99,6 +109,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); } + @BeforeMapping + public void withSourceAndTargetBeforeMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + @BeforeMapping public void withSourceAndTargetBeforeMapping(List source, @MappingTarget List target) { INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); @@ -115,6 +130,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); } + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + @BeforeMapping public void withTargetBeforeMapping(@MappingTarget List target) { INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); @@ -140,6 +160,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); } + @AfterMapping + public void withSourceAfterMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + @AfterMapping public void withSourceAfterMapping(List source) { INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); @@ -160,6 +185,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); } + @AfterMapping + public void withSourceAndTargetAfterMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + @AfterMapping public void withSourceAndTargetAfterMapping(List source, @MappingTarget List target) { INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); @@ -175,6 +205,11 @@ public abstract class BaseMapper { INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); } + @AfterMapping + public void withTargetAfterMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + @AfterMapping @Qualified public void withTargetAfterMappingQualified(@MappingTarget Target target) { diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/CallbackMethodTest.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/CallbackMethodTest.java index cb95c2738..cd65ddcc3 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/callbacks/CallbackMethodTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/CallbackMethodTest.java @@ -43,7 +43,8 @@ import static org.fest.assertions.Assertions.assertThat; */ @RunWith( AnnotationProcessorTestRunner.class ) @WithClasses( { ClassContainingCallbacks.class, Invocation.class, Source.class, Target.class, SourceTargetMapper.class, - SourceTargetCollectionMapper.class, BaseMapper.class, Qualified.class }) + SourceTargetCollectionMapper.class, BaseMapper.class, Qualified.class, + SourceEnum.class, TargetEnum.class }) @IssueKey("14") public class CallbackMethodTest { @@ -121,6 +122,19 @@ public class CallbackMethodTest { assertQualifiedInvocations( BaseMapper.getInvocations(), sourceList, targetList ); } + @Test + public void callbackMethodsForEnumMappingCalled() { + SourceEnum source = SourceEnum.B; + TargetEnum target = SourceTargetMapper.INSTANCE.toTargetEnum( source ); + + List invocations = new ArrayList(); + invocations.addAll( allBeforeMappingMethods( source, target, TargetEnum.class ) ); + invocations.addAll( allAfterMappingMethods( source, target, TargetEnum.class ) ); + + assertThat( invocations ).isEqualTo( ClassContainingCallbacks.getInvocations() ); + assertThat( invocations ).isEqualTo( BaseMapper.getInvocations() ); + } + private void assertBeanMappingInvocations(List invocations) { Source source = createSource(); Target target = createResultTarget(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/ClassContainingCallbacks.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/ClassContainingCallbacks.java index 71c47e7e6..6aeda33f2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/callbacks/ClassContainingCallbacks.java +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/ClassContainingCallbacks.java @@ -49,6 +49,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) ); } + @BeforeMapping + public void withSourceBeforeMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); + } + @BeforeMapping public void withSourceBeforeMapping(List source) { INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) ); @@ -81,6 +86,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); } + @BeforeMapping + public void withSourceAndTargetTypeBeforeMapping(SourceEnum source, @TargetType Class targetClass) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); + } + @BeforeMapping public void withSourceAndTargetTypeBeforeMapping(List source, @TargetType Class targetClass) { INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) ); @@ -96,6 +106,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); } + @BeforeMapping + public void withSourceAndTargetBeforeMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); + } + @BeforeMapping public void withSourceAndTargetBeforeMapping(List source, @MappingTarget List target) { INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) ); @@ -112,6 +127,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); } + @BeforeMapping + public void withTargetBeforeMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); + } + @BeforeMapping public void withTargetBeforeMapping(@MappingTarget List target) { INVOCATIONS.add( new Invocation( "withTargetBeforeMapping", target ) ); @@ -137,6 +157,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); } + @AfterMapping + public void withSourceAfterMapping(SourceEnum source) { + INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); + } + @AfterMapping public void withSourceAfterMapping(List source) { INVOCATIONS.add( new Invocation( "withSourceAfterMapping", source ) ); @@ -157,6 +182,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); } + @AfterMapping + public void withSourceAndTargetAfterMapping(SourceEnum source, @MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); + } + @AfterMapping public void withSourceAndTargetAfterMapping(List source, @MappingTarget List target) { INVOCATIONS.add( new Invocation( "withSourceAndTargetAfterMapping", source, target ) ); @@ -172,6 +202,11 @@ public class ClassContainingCallbacks { INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); } + @AfterMapping + public void withTargetAfterMapping(@MappingTarget TargetEnum target) { + INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) ); + } + @AfterMapping @Qualified public void withTargetAfterMappingQualified(@MappingTarget Target target) { diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceEnum.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceEnum.java new file mode 100644 index 000000000..0c4a4f460 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceEnum.java @@ -0,0 +1,27 @@ +/** + * Copyright 2012-2015 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.callbacks; + +/** + * @author Andreas Gudian + * + */ +public enum SourceEnum { + A, B, C; +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceTargetMapper.java index 96d713ec8..e632c6bb8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/SourceTargetMapper.java @@ -34,4 +34,6 @@ public abstract class SourceTargetMapper extends BaseMapper { @BeanMapping(qualifiedBy = Qualified.class) public abstract Target qualifiedSourceToTarget(Source source); + + public abstract TargetEnum toTargetEnum(SourceEnum sourceEnum); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/callbacks/TargetEnum.java b/processor/src/test/java/org/mapstruct/ap/test/callbacks/TargetEnum.java new file mode 100644 index 000000000..aec8c34d6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/callbacks/TargetEnum.java @@ -0,0 +1,27 @@ +/** + * Copyright 2012-2015 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.callbacks; + +/** + * @author Andreas Gudian + * + */ +public enum TargetEnum { + A, B, C; +}