#328 if a source property is assignable to the target property, do not apply any built-in conversions

This commit is contained in:
Andreas Gudian 2014-10-21 20:05:12 +02:00
parent 54b8747e09
commit 8c3e32472b
5 changed files with 66 additions and 15 deletions

View File

@ -178,10 +178,9 @@ public class MappingResolverImpl implements MappingResolver {
private Assignment getTargetAssignment(Type sourceType, Type targetType) { private Assignment getTargetAssignment(Type sourceType, Type targetType) {
// first simple mapping method // first simple mapping method
Assignment referencedMethod = resolveViaMethod( sourceType, targetType ); Assignment referencedMethod = resolveViaMethod( sourceType, targetType, false );
if ( referencedMethod != null ) { if ( referencedMethod != null ) {
referencedMethod.setAssignment( AssignmentFactory.createSimple( sourceReference ) ); referencedMethod.setAssignment( AssignmentFactory.createSimple( sourceReference ) );
usedVirtualMappings.addAll( virtualMethodCandidates );
return referencedMethod; return referencedMethod;
} }
@ -198,21 +197,29 @@ public class MappingResolverImpl implements MappingResolver {
return conversion; return conversion;
} }
// 2 step method, first: method(method(souurce)) // check for a built-in method
Assignment builtInMethod = resolveViaBuiltInMethod( sourceType, targetType );
if ( builtInMethod != null ) {
builtInMethod.setAssignment( AssignmentFactory.createSimple( sourceReference ) );
usedVirtualMappings.addAll( virtualMethodCandidates );
return builtInMethod;
}
// 2 step method, first: method(method(source))
referencedMethod = resolveViaMethodAndMethod( sourceType, targetType ); referencedMethod = resolveViaMethodAndMethod( sourceType, targetType );
if ( referencedMethod != null ) { if ( referencedMethod != null ) {
usedVirtualMappings.addAll( virtualMethodCandidates ); usedVirtualMappings.addAll( virtualMethodCandidates );
return referencedMethod; return referencedMethod;
} }
// 2 step method, then: method(conversion(souurce)) // 2 step method, then: method(conversion(source))
referencedMethod = resolveViaConversionAndMethod( sourceType, targetType ); referencedMethod = resolveViaConversionAndMethod( sourceType, targetType );
if ( referencedMethod != null ) { if ( referencedMethod != null ) {
usedVirtualMappings.addAll( virtualMethodCandidates ); usedVirtualMappings.addAll( virtualMethodCandidates );
return referencedMethod; return referencedMethod;
} }
// 2 step method, finally: conversion(method(souurce)) // 2 step method, finally: conversion(method(source))
conversion = resolveViaMethodAndConversion( sourceType, targetType ); conversion = resolveViaMethodAndConversion( sourceType, targetType );
if ( conversion != null ) { if ( conversion != null ) {
usedVirtualMappings.addAll( virtualMethodCandidates ); usedVirtualMappings.addAll( virtualMethodCandidates );
@ -239,7 +246,7 @@ public class MappingResolverImpl implements MappingResolver {
* Returns a reference to a method mapping the given source type to the given target type, if such a method * Returns a reference to a method mapping the given source type to the given target type, if such a method
* exists. * exists.
*/ */
private Assignment resolveViaMethod(Type sourceType, Type targetType) { private Assignment resolveViaMethod(Type sourceType, Type targetType, boolean considerBuiltInMethods) {
// first try to find a matching source method // first try to find a matching source method
SourceMethod matchingSourceMethod = getBestMatch( methods, sourceType, targetType ); SourceMethod matchingSourceMethod = getBestMatch( methods, sourceType, targetType );
@ -248,14 +255,20 @@ public class MappingResolverImpl implements MappingResolver {
return getMappingMethodReference( matchingSourceMethod, targetType ); return getMappingMethodReference( matchingSourceMethod, targetType );
} }
// then a matching built-in method if ( considerBuiltInMethods ) {
return resolveViaBuiltInMethod( sourceType, targetType );
}
return null;
}
private Assignment resolveViaBuiltInMethod(Type sourceType, Type targetType) {
BuiltInMethod matchingBuiltInMethod = BuiltInMethod matchingBuiltInMethod =
getBestMatch( builtInMethods.getBuiltInMethods(), sourceType, targetType ); getBestMatch( builtInMethods.getBuiltInMethods(), sourceType, targetType );
if ( matchingBuiltInMethod != null ) { if ( matchingBuiltInMethod != null ) {
virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) ); virtualMethodCandidates.add( new VirtualMappingMethod( matchingBuiltInMethod ) );
ConversionContext ctx = ConversionContext ctx = new DefaultConversionContext( typeFactory, targetType, dateFormat );
new DefaultConversionContext( typeFactory, targetType, dateFormat );
Assignment methodReference = AssignmentFactory.createMethodReference( matchingBuiltInMethod, ctx ); Assignment methodReference = AssignmentFactory.createMethodReference( matchingBuiltInMethod, ctx );
methodReference.setAssignment( AssignmentFactory.createSimple( sourceReference ) ); methodReference.setAssignment( AssignmentFactory.createSimple( sourceReference ) );
return methodReference; return methodReference;
@ -291,12 +304,14 @@ public class MappingResolverImpl implements MappingResolver {
if ( methodYCandidate.getSourceParameters().size() == 1 ) { if ( methodYCandidate.getSourceParameters().size() == 1 ) {
methodRefY = resolveViaMethod( methodRefY = resolveViaMethod(
methodYCandidate.getSourceParameters().get( 0 ).getType(), methodYCandidate.getSourceParameters().get( 0 ).getType(),
targetType targetType,
true
); );
if ( methodRefY != null ) { if ( methodRefY != null ) {
Assignment methodRefX = resolveViaMethod( Assignment methodRefX = resolveViaMethod(
sourceType, sourceType,
methodYCandidate.getSourceParameters().get( 0 ).getType() methodYCandidate.getSourceParameters().get( 0 ).getType(),
true
); );
if ( methodRefX != null ) { if ( methodRefX != null ) {
methodRefY.setAssignment( methodRefX ); methodRefY.setAssignment( methodRefX );
@ -333,7 +348,8 @@ public class MappingResolverImpl implements MappingResolver {
if ( methodYCandidate.getSourceParameters().size() == 1 ) { if ( methodYCandidate.getSourceParameters().size() == 1 ) {
methodRefY = resolveViaMethod( methodRefY = resolveViaMethod(
methodYCandidate.getSourceParameters().get( 0 ).getType(), methodYCandidate.getSourceParameters().get( 0 ).getType(),
targetType targetType,
true
); );
if ( methodRefY != null ) { if ( methodRefY != null ) {
Assignment conversionXRef = resolveViaConversion( Assignment conversionXRef = resolveViaConversion(
@ -376,7 +392,8 @@ public class MappingResolverImpl implements MappingResolver {
if ( methodXCandidate.getSourceParameters().size() == 1 ) { if ( methodXCandidate.getSourceParameters().size() == 1 ) {
Assignment methodRefX = resolveViaMethod( Assignment methodRefX = resolveViaMethod(
sourceType, sourceType,
methodXCandidate.getReturnType() methodXCandidate.getReturnType(),
true
); );
if ( methodRefX != null ) { if ( methodRefX != null ) {
conversionYRef = resolveViaConversion( methodXCandidate.getReturnType(), targetType ); conversionYRef = resolveViaConversion( methodXCandidate.getReturnType(), targetType );

View File

@ -36,6 +36,7 @@ public class Source {
private Boolean boolBool; private Boolean boolBool;
private char c; private char c;
private Character cc; private Character cc;
private Object object;
public byte getB() { public byte getB() {
return b; return b;
@ -164,4 +165,12 @@ public class Source {
public void setCc(Character cc) { public void setCc(Character cc) {
this.cc = cc; this.cc = cc;
} }
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
} }

View File

@ -19,6 +19,7 @@
package org.mapstruct.ap.test.conversion.string; package org.mapstruct.ap.test.conversion.string;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@Mapper @Mapper
@ -26,6 +27,7 @@ public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mapping( source = "object", ignore = true )
Target sourceToTarget(Source source); Target sourceToTarget(Source source);
Source targetToSource(Target target); Source targetToSource(Target target);

View File

@ -18,13 +18,14 @@
*/ */
package org.mapstruct.ap.test.conversion.string; package org.mapstruct.ap.test.conversion.string;
import static org.fest.assertions.Assertions.assertThat;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
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;
@WithClasses({ @WithClasses({
Source.class, Source.class,
Target.class, Target.class,
@ -33,6 +34,8 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
@RunWith(AnnotationProcessorTestRunner.class) @RunWith(AnnotationProcessorTestRunner.class)
public class StringConversionTest { public class StringConversionTest {
private static final String STRING_CONTANT = "String contant";
@Test @Test
public void shouldApplyStringConversions() { public void shouldApplyStringConversions() {
Source source = new Source(); Source source = new Source();
@ -114,4 +117,16 @@ public class StringConversionTest {
assertThat( source.getC() ).isEqualTo( 'G' ); assertThat( source.getC() ).isEqualTo( 'G' );
assertThat( source.getCc() ).isEqualTo( 'H' ); assertThat( source.getCc() ).isEqualTo( 'H' );
} }
@Test
@IssueKey( "328" )
public void stringShouldBeMappedToObjectByReference() {
Target target = new Target();
target.setObject( STRING_CONTANT );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
// no conversion, no built-in method
assertThat( source.getObject() ).isSameAs( STRING_CONTANT );
}
} }

View File

@ -36,6 +36,7 @@ public class Target {
private String boolBool; private String boolBool;
private String c; private String c;
private String cc; private String cc;
private String object;
public String getB() { public String getB() {
return b; return b;
@ -165,4 +166,11 @@ public class Target {
this.cc = cc; this.cc = cc;
} }
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
} }