mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#14 Consider qualifiers when selecting @BeforeMapping/@AfterMapping methods
This commit is contained in:
parent
ac8320b0a3
commit
68fc3af645
@ -163,9 +163,9 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
sortPropertyMappingsByDependencies();
|
sortPropertyMappingsByDependencies();
|
||||||
|
|
||||||
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
||||||
LifecycleCallbackFactory.beforeMappingMethods( method, ctx );
|
LifecycleCallbackFactory.beforeMappingMethods( method, qualifiers, ctx );
|
||||||
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
||||||
LifecycleCallbackFactory.afterMappingMethods( method, ctx );
|
LifecycleCallbackFactory.afterMappingMethods( method, qualifiers, ctx );
|
||||||
|
|
||||||
return new BeanMappingMethod(
|
return new BeanMappingMethod(
|
||||||
method,
|
method,
|
||||||
|
@ -150,9 +150,9 @@ public class IterableMappingMethod extends MappingMethod {
|
|||||||
= ctx.getMappingResolver().getFactoryMethod( method, method.getResultType(), null, null );
|
= ctx.getMappingResolver().getFactoryMethod( method, method.getResultType(), null, null );
|
||||||
|
|
||||||
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
||||||
LifecycleCallbackFactory.beforeMappingMethods( method, ctx );
|
LifecycleCallbackFactory.beforeMappingMethods( method, qualifiers, ctx );
|
||||||
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
||||||
LifecycleCallbackFactory.afterMappingMethods( method, ctx );
|
LifecycleCallbackFactory.afterMappingMethods( method, qualifiers, ctx );
|
||||||
|
|
||||||
return new IterableMappingMethod(
|
return new IterableMappingMethod(
|
||||||
method,
|
method,
|
||||||
|
@ -19,14 +19,19 @@
|
|||||||
package org.mapstruct.ap.model;
|
package org.mapstruct.ap.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
|
import javax.lang.model.type.TypeMirror;
|
||||||
|
|
||||||
import org.mapstruct.ap.model.common.Parameter;
|
import org.mapstruct.ap.model.common.Parameter;
|
||||||
import org.mapstruct.ap.model.common.Type;
|
import org.mapstruct.ap.model.common.Type;
|
||||||
import org.mapstruct.ap.model.source.Method;
|
import org.mapstruct.ap.model.source.Method;
|
||||||
import org.mapstruct.ap.model.source.SourceMethod;
|
import org.mapstruct.ap.model.source.SourceMethod;
|
||||||
|
import org.mapstruct.ap.model.source.selector.QualifierSelector;
|
||||||
|
import org.mapstruct.ap.model.source.selector.SelectionCriteria;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating lists of appropriate {@link LifecycleCallbackMethodReference}s
|
* Factory for creating lists of appropriate {@link LifecycleCallbackMethodReference}s
|
||||||
@ -40,27 +45,95 @@ public final class LifecycleCallbackFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param method the method to obtain the beforeMapping methods for
|
* @param method the method to obtain the beforeMapping methods for
|
||||||
|
* @param qualifiers method qualifiers
|
||||||
* @param ctx the builder context
|
* @param ctx the builder context
|
||||||
* @return all applicable {@code @BeforeMapping} methods for the given method
|
* @return all applicable {@code @BeforeMapping} methods for the given method
|
||||||
*/
|
*/
|
||||||
public static List<LifecycleCallbackMethodReference> beforeMappingMethods(
|
public static List<LifecycleCallbackMethodReference> beforeMappingMethods(
|
||||||
Method method, MappingBuilderContext ctx) {
|
Method method, List<TypeMirror> qualifiers, MappingBuilderContext ctx) {
|
||||||
return collectLifecycleCallbackMethods( method, filterBeforeMappingMethods( ctx.getSourceModel() ), ctx );
|
return collectLifecycleCallbackMethods(
|
||||||
|
method,
|
||||||
|
qualifiers,
|
||||||
|
filterBeforeMappingMethods( ctx.getSourceModel() ),
|
||||||
|
ctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param method the method to obtain the afterMapping methods for
|
* @param method the method to obtain the afterMapping methods for
|
||||||
|
* @param qualifiers method qualifiers
|
||||||
* @param ctx the builder context
|
* @param ctx the builder context
|
||||||
* @return all applicable {@code @AfterMapping} methods for the given method
|
* @return all applicable {@code @AfterMapping} methods for the given method
|
||||||
*/
|
*/
|
||||||
public static List<LifecycleCallbackMethodReference> afterMappingMethods(
|
public static List<LifecycleCallbackMethodReference> afterMappingMethods(
|
||||||
Method method, MappingBuilderContext ctx) {
|
Method method, List<TypeMirror> qualifiers, MappingBuilderContext ctx) {
|
||||||
return collectLifecycleCallbackMethods( method, filterAfterMappingMethods( ctx.getSourceModel() ), ctx );
|
return collectLifecycleCallbackMethods(
|
||||||
|
method,
|
||||||
|
qualifiers,
|
||||||
|
filterAfterMappingMethods( ctx.getSourceModel() ),
|
||||||
|
ctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<LifecycleCallbackMethodReference> collectLifecycleCallbackMethods(
|
private static List<LifecycleCallbackMethodReference> collectLifecycleCallbackMethods(
|
||||||
Method method, List<SourceMethod> callbackMethods, MappingBuilderContext ctx) {
|
Method method, List<TypeMirror> qualifiers, List<SourceMethod> callbackMethods, MappingBuilderContext ctx) {
|
||||||
|
|
||||||
|
Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod =
|
||||||
|
new HashMap<SourceMethod, List<Parameter>>();
|
||||||
|
|
||||||
|
List<SourceMethod> candidates =
|
||||||
|
filterCandidatesByType( method, callbackMethods, parameterAssignmentsForSourceMethod, ctx );
|
||||||
|
|
||||||
|
candidates = filterCandidatesByQualifiers( method, qualifiers, candidates, ctx );
|
||||||
|
|
||||||
|
return toLifecycleCallbackMethodRefs( candidates, parameterAssignmentsForSourceMethod, ctx );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<SourceMethod> filterCandidatesByQualifiers(Method method, List<TypeMirror> qualifiers,
|
||||||
|
List<SourceMethod> candidates,
|
||||||
|
MappingBuilderContext ctx) {
|
||||||
|
QualifierSelector selector = new QualifierSelector( ctx.getTypeUtils(), ctx.getElementUtils() );
|
||||||
|
|
||||||
|
return selector.getMatchingMethods( method, candidates, null, null, new SelectionCriteria(
|
||||||
|
qualifiers,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
false ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<LifecycleCallbackMethodReference> toLifecycleCallbackMethodRefs(
|
||||||
|
List<SourceMethod> candidates, Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod,
|
||||||
|
MappingBuilderContext ctx) {
|
||||||
|
|
||||||
|
List<LifecycleCallbackMethodReference> result = new ArrayList<LifecycleCallbackMethodReference>();
|
||||||
|
for ( SourceMethod candidate : candidates ) {
|
||||||
|
markMapperReferenceAsUsed( ctx.getMapperReferences(), candidate );
|
||||||
|
result.add( new LifecycleCallbackMethodReference(
|
||||||
|
candidate,
|
||||||
|
parameterAssignmentsForSourceMethod.get( candidate ) ) );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<SourceMethod> filterCandidatesByType(Method method,
|
||||||
|
List<SourceMethod> callbackMethods, Map<SourceMethod, List<Parameter>> parameterAssignmentsForSourceMethod,
|
||||||
|
MappingBuilderContext ctx) {
|
||||||
|
|
||||||
|
List<SourceMethod> candidates = new ArrayList<SourceMethod>();
|
||||||
|
|
||||||
|
List<Parameter> availableParams = getAvailableParameters( method, ctx );
|
||||||
|
for ( SourceMethod callback : callbackMethods ) {
|
||||||
|
List<Parameter> parameterAssignments = getParameterAssignments( availableParams, callback.getParameters() );
|
||||||
|
|
||||||
|
if ( parameterAssignments != null
|
||||||
|
&& callback.matches( extractSourceTypes( parameterAssignments ), method.getResultType() ) ) {
|
||||||
|
|
||||||
|
parameterAssignmentsForSourceMethod.put( callback, parameterAssignments );
|
||||||
|
candidates.add( callback );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return candidates;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Parameter> getAvailableParameters(Method method, MappingBuilderContext ctx) {
|
||||||
List<Parameter> availableParams = new ArrayList<Parameter>( method.getParameters() );
|
List<Parameter> availableParams = new ArrayList<Parameter>( method.getParameters() );
|
||||||
if ( method.getMappingTargetParameter() == null ) {
|
if ( method.getMappingTargetParameter() == null ) {
|
||||||
availableParams.add( new Parameter( null, method.getResultType(), true, false ) );
|
availableParams.add( new Parameter( null, method.getResultType(), true, false ) );
|
||||||
@ -73,23 +146,10 @@ public final class LifecycleCallbackFactory {
|
|||||||
true );
|
true );
|
||||||
|
|
||||||
availableParams.add( targetTypeParameter );
|
availableParams.add( targetTypeParameter );
|
||||||
|
return availableParams;
|
||||||
List<LifecycleCallbackMethodReference> result = new ArrayList<LifecycleCallbackMethodReference>();
|
|
||||||
|
|
||||||
for ( SourceMethod callback : callbackMethods ) {
|
|
||||||
List<Parameter> parameterAssignments = getParameterAssignments( availableParams, callback.getParameters() );
|
|
||||||
|
|
||||||
if ( parameterAssignments != null
|
|
||||||
&& callback.matches( extractSourceTypes( parameterAssignments ), method.getResultType() ) ) {
|
|
||||||
|
|
||||||
markMapperReferenceAsUsed( ctx.getMapperReferences(), callback );
|
|
||||||
result.add( new LifecycleCallbackMethodReference( callback, parameterAssignments ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void markMapperReferenceAsUsed(List<MapperReference> references, SourceMethod method) {
|
private static void markMapperReferenceAsUsed(List<MapperReference> references, Method method) {
|
||||||
for ( MapperReference ref : references ) {
|
for ( MapperReference ref : references ) {
|
||||||
if ( ref.getType().equals( method.getDeclaringMapper() ) ) {
|
if ( ref.getType().equals( method.getDeclaringMapper() ) ) {
|
||||||
ref.setUsed( !method.isStatic() );
|
ref.setUsed( !method.isStatic() );
|
||||||
|
@ -192,9 +192,9 @@ public class MapMappingMethod extends MappingMethod {
|
|||||||
valueAssignment = new LocalVarWrapper( valueAssignment, method.getThrownTypes() );
|
valueAssignment = new LocalVarWrapper( valueAssignment, method.getThrownTypes() );
|
||||||
|
|
||||||
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
List<LifecycleCallbackMethodReference> beforeMappingMethods =
|
||||||
LifecycleCallbackFactory.beforeMappingMethods( method, ctx );
|
LifecycleCallbackFactory.beforeMappingMethods( method, null, ctx );
|
||||||
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
List<LifecycleCallbackMethodReference> afterMappingMethods =
|
||||||
LifecycleCallbackFactory.afterMappingMethods( method, ctx );
|
LifecycleCallbackFactory.afterMappingMethods( method, null, ctx );
|
||||||
|
|
||||||
return new MapMappingMethod(
|
return new MapMappingMethod(
|
||||||
method,
|
method,
|
||||||
|
@ -34,16 +34,18 @@ import org.mapstruct.ap.model.source.SourceMethod;
|
|||||||
import org.mapstruct.ap.prism.QualifierPrism;
|
import org.mapstruct.ap.prism.QualifierPrism;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This selector selects a best match based on qualifiers name.
|
* This selector selects a best match based on qualifier annotations.
|
||||||
* <p>
|
* <p>
|
||||||
* A method is said to be marked with a qualifier annotation if the class in which it resides is annotated with a
|
* A method is said to be marked with a qualifier annotation if the class in which it resides is annotated with a
|
||||||
* qualifier annotation or if the method itself is annotated with a qualifier annotation or both.
|
* qualifier annotation or if the method itself is annotated with a qualifier annotation or both.
|
||||||
* <p>
|
* <p>
|
||||||
* Rules:
|
* Rules:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>If a method is marked with a qualifier annotation, it does not contribute to a match otherwise and is hence
|
* <li>If no qualifiers are requested in the selection criteria, then only candidate methods without any qualifier
|
||||||
* removed from the list of potential mapping methods</li>
|
* annotations remain in the list of potential candidates</li>
|
||||||
* <li>If multiple qualifiers (qualifedBy) are specified, all should match to make a match.</li>
|
* <li>If multiple qualifiers (qualifedBy) are specified, then all of them need to be present at a candidate for it to
|
||||||
|
* match.</li>
|
||||||
|
* <li>If no candidate matches the required qualifiers, then all candidates are returned.</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
|
@ -46,16 +46,34 @@ public abstract class BaseMapper {
|
|||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(Source source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceBeforeMapping(List<Source> source) {
|
public void withSourceBeforeMapping(List<Source> source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(List<Source> source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceBeforeMapping(Map<String, Source> source) {
|
public void withSourceBeforeMapping(Map<String, Source> source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(Map<String, Source> source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceAsObjectBeforeMapping(Object source) {
|
public void withSourceAsObjectBeforeMapping(Object source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
|
||||||
@ -157,16 +175,34 @@ public abstract class BaseMapper {
|
|||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget Target target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAfterMapping(@MappingTarget List<Target> target) {
|
public void withTargetAfterMapping(@MappingTarget List<Target> target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget List<Target> target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
|
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget Map<String, Target> target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
|
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );
|
||||||
@ -184,5 +220,4 @@ public abstract class BaseMapper {
|
|||||||
public static void reset() {
|
public static void reset() {
|
||||||
INVOCATIONS.clear();
|
INVOCATIONS.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.fest.assertions.Assertions;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@ -35,6 +34,8 @@ import org.mapstruct.ap.testutil.IssueKey;
|
|||||||
import org.mapstruct.ap.testutil.WithClasses;
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for callback methods that are defined using {@link BeforeMapping} / {@link AfterMapping}
|
* Test for callback methods that are defined using {@link BeforeMapping} / {@link AfterMapping}
|
||||||
*
|
*
|
||||||
@ -42,7 +43,7 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
|||||||
*/
|
*/
|
||||||
@RunWith( AnnotationProcessorTestRunner.class )
|
@RunWith( AnnotationProcessorTestRunner.class )
|
||||||
@WithClasses( { ClassContainingCallbacks.class, Invocation.class, Source.class, Target.class, SourceTargetMapper.class,
|
@WithClasses( { ClassContainingCallbacks.class, Invocation.class, Source.class, Target.class, SourceTargetMapper.class,
|
||||||
SourceTargetCollectionMapper.class, BaseMapper.class } )
|
SourceTargetCollectionMapper.class, BaseMapper.class, Qualified.class })
|
||||||
@IssueKey("14")
|
@IssueKey("14")
|
||||||
public class CallbackMethodTest {
|
public class CallbackMethodTest {
|
||||||
|
|
||||||
@ -103,12 +104,29 @@ public class CallbackMethodTest {
|
|||||||
assertMapMappingInvocations( BaseMapper.getInvocations() );
|
assertMapMappingInvocations( BaseMapper.getInvocations() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void qualifiersAreEvaluatedCorrectly() {
|
||||||
|
Source source = createSource();
|
||||||
|
Target target = SourceTargetMapper.INSTANCE.qualifiedSourceToTarget( source );
|
||||||
|
|
||||||
|
assertQualifiedInvocations( ClassContainingCallbacks.getInvocations(), source, target );
|
||||||
|
assertQualifiedInvocations( BaseMapper.getInvocations(), source, target );
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
List<Source> sourceList = Arrays.asList( createSource() );
|
||||||
|
List<Target> targetList = SourceTargetCollectionMapper.INSTANCE.qualifiedSourceToTarget( sourceList );
|
||||||
|
|
||||||
|
assertQualifiedInvocations( ClassContainingCallbacks.getInvocations(), sourceList, targetList );
|
||||||
|
assertQualifiedInvocations( BaseMapper.getInvocations(), sourceList, targetList );
|
||||||
|
}
|
||||||
|
|
||||||
private void assertBeanMappingInvocations(List<Invocation> invocations) {
|
private void assertBeanMappingInvocations(List<Invocation> invocations) {
|
||||||
Source source = createSource();
|
Source source = createSource();
|
||||||
Target target = createResultTarget();
|
Target target = createResultTarget();
|
||||||
Target emptyTarget = createEmptyTarget();
|
Target emptyTarget = createEmptyTarget();
|
||||||
|
|
||||||
Assertions.assertThat( invocations ).isEqualTo( beanMappingInvocationList( source, target, emptyTarget ) );
|
assertThat( invocations ).isEqualTo( beanMappingInvocationList( source, target, emptyTarget ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertIterableMappingInvocations(List<Invocation> invocations) {
|
private void assertIterableMappingInvocations(List<Invocation> invocations) {
|
||||||
@ -168,7 +186,7 @@ public class CallbackMethodTest {
|
|||||||
expected.addAll( beanMappingInvocationList( source, target, emptyTarget ) );
|
expected.addAll( beanMappingInvocationList( source, target, emptyTarget ) );
|
||||||
expected.addAll( allAfterMappingMethods( sourceCollection, targetCollection, targetCollectionClass ) );
|
expected.addAll( allAfterMappingMethods( sourceCollection, targetCollection, targetCollectionClass ) );
|
||||||
|
|
||||||
Assertions.assertThat( invocations ).isEqualTo( expected );
|
assertThat( invocations ).isEqualTo( expected );
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Invocation> beanMappingInvocationList(Object source, Object target, Object emptyTarget) {
|
private List<Invocation> beanMappingInvocationList(Object source, Object target, Object emptyTarget) {
|
||||||
@ -202,6 +220,24 @@ public class CallbackMethodTest {
|
|||||||
new Invocation( "withTargetAsObjectBeforeMapping", emptyTarget ) ) );
|
new Invocation( "withTargetAsObjectBeforeMapping", emptyTarget ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertQualifiedInvocations(List<Invocation> actual, Object source, Object target) {
|
||||||
|
assertThat( actual ).isEqualTo( allQualifiedCallbackMethods( source, target ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Invocation> allQualifiedCallbackMethods(Object source, Object target) {
|
||||||
|
List<Invocation> invocations = new ArrayList<Invocation>();
|
||||||
|
invocations.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
|
||||||
|
if ( source instanceof List || source instanceof Map ) {
|
||||||
|
invocations.addAll(
|
||||||
|
beanMappingInvocationList( createSource(), createResultTarget(), createEmptyTarget() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
invocations.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
|
||||||
|
return invocations;
|
||||||
|
}
|
||||||
|
|
||||||
private Source createSource() {
|
private Source createSource() {
|
||||||
Source source = new Source();
|
Source source = new Source();
|
||||||
source.setFoo( "foo" );
|
source.setFoo( "foo" );
|
||||||
|
@ -43,21 +43,54 @@ public class ClassContainingCallbacks {
|
|||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(Source source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceBeforeMapping(List<Source> source) {
|
public void withSourceBeforeMapping(List<Source> source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(List<Source> source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceBeforeMapping(Map<String, Source> source) {
|
public void withSourceBeforeMapping(Map<String, Source> source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
@Qualified
|
||||||
|
public void withSourceBeforeMappingQualified(Map<String, Source> source) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceBeforeMappingQualified", source ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceAsObjectBeforeMapping(Object source) {
|
public void withSourceAsObjectBeforeMapping(Object source) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
|
INVOCATIONS.add( new Invocation( "withSourceAsObjectBeforeMapping", source ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
public <T> void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class<T> targetClass) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
public <T> void withSourceAndTargetTypeBeforeMapping(List<Source> source, @TargetType Class<T> targetClass) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
public <T> void withSourceAndTargetTypeBeforeMapping(Map<String, Source> source, @TargetType Class<T> targetClass) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
@BeforeMapping
|
||||||
public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) {
|
public void withSourceAndTargetBeforeMapping(Source source, @MappingTarget Target target) {
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) );
|
INVOCATIONS.add( new Invocation( "withSourceAndTargetBeforeMapping", source, target ) );
|
||||||
@ -94,21 +127,6 @@ public class ClassContainingCallbacks {
|
|||||||
INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAsObjectBeforeMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeMapping
|
|
||||||
public <T> void withSourceAndTargetTypeBeforeMapping(Source source, @TargetType Class<T> targetClass) {
|
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeMapping
|
|
||||||
public <T> void withSourceAndTargetTypeBeforeMapping(List<Source> source, @TargetType Class<T> targetClass) {
|
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeMapping
|
|
||||||
public <T> void withSourceAndTargetTypeBeforeMapping(Map<String, Source> source, @TargetType Class<T> targetClass) {
|
|
||||||
INVOCATIONS.add( new Invocation( "withSourceAndTargetTypeBeforeMapping", source, targetClass ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void noArgsAfterMapping() {
|
public void noArgsAfterMapping() {
|
||||||
INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) );
|
INVOCATIONS.add( new Invocation( "noArgsAfterMapping" ) );
|
||||||
@ -154,16 +172,34 @@ public class ClassContainingCallbacks {
|
|||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget Target target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAfterMapping(@MappingTarget List<Target> target) {
|
public void withTargetAfterMapping(@MappingTarget List<Target> target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget List<Target> target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
|
public void withTargetAfterMapping(@MappingTarget Map<String, Target> target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAfterMapping", target ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
@Qualified
|
||||||
|
public void withTargetAfterMappingQualified(@MappingTarget Map<String, Target> target) {
|
||||||
|
INVOCATIONS.add( new Invocation( "withTargetAfterMappingQualified", target ) );
|
||||||
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
|
public void withTargetAsObjectAfterMapping(@MappingTarget Object target) {
|
||||||
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );
|
INVOCATIONS.add( new Invocation( "withTargetAsObjectAfterMapping", target ) );
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.mapstruct.Qualifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Gudian
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Qualifier
|
||||||
|
public @interface Qualified {
|
||||||
|
|
||||||
|
}
|
@ -21,6 +21,7 @@ package org.mapstruct.ap.test.callbacks;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.mapstruct.IterableMapping;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -36,6 +37,9 @@ public abstract class SourceTargetCollectionMapper extends BaseMapper {
|
|||||||
|
|
||||||
public abstract void sourceToTarget(List<Source> source, @MappingTarget List<Target> target);
|
public abstract void sourceToTarget(List<Source> source, @MappingTarget List<Target> target);
|
||||||
|
|
||||||
|
@IterableMapping(qualifiedBy = Qualified.class)
|
||||||
|
public abstract List<Target> qualifiedSourceToTarget(List<Source> source);
|
||||||
|
|
||||||
public abstract Map<String, Target> sourceToTarget(Map<String, Source> source);
|
public abstract Map<String, Target> sourceToTarget(Map<String, Source> source);
|
||||||
|
|
||||||
public abstract void sourceToTarget(Map<String, Source> source, @MappingTarget Map<String, Target> target);
|
public abstract void sourceToTarget(Map<String, Source> source, @MappingTarget Map<String, Target> target);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.callbacks;
|
package org.mapstruct.ap.test.callbacks;
|
||||||
|
|
||||||
|
import org.mapstruct.BeanMapping;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -30,4 +31,7 @@ public abstract class SourceTargetMapper extends BaseMapper {
|
|||||||
public static final SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
public static final SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
||||||
|
|
||||||
public abstract void sourceToTarget(Source source, @MappingTarget Target target);
|
public abstract void sourceToTarget(Source source, @MappingTarget Target target);
|
||||||
|
|
||||||
|
@BeanMapping(qualifiedBy = Qualified.class)
|
||||||
|
public abstract Target qualifiedSourceToTarget(Source source);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user