#104 Fixing issue which prevented the mapping of a property which has no setter in the source and is named as source via @Mapping

This commit is contained in:
Gunnar Morling 2014-01-21 22:42:55 +01:00
parent 196d91324a
commit 5dd3ab2bec
6 changed files with 58 additions and 14 deletions

View File

@ -32,6 +32,10 @@ import org.mapstruct.ap.util.Strings;
/**
* Represents a mapping method with source and target type and the mappings between the properties of source and target
* type.
* <p>
* A method can either be configured by itself or by another method for the inverse mapping direction (one of
* {@link #setMappings(Map)}, {@link #setIterableMapping(IterableMapping)} or {@link #setMapMapping(MapMapping)} will be
* called in this case).
*
* @author Gunnar Morling
*/
@ -40,13 +44,14 @@ public class Method {
private final Type declaringMapper;
private final ExecutableElement executable;
private final List<Parameter> parameters;
private final Parameter targetParameter;
private final Type returnType;
private Map<String, List<Mapping>> mappings;
private IterableMapping iterableMapping;
private MapMapping mapMapping;
private final Parameter targetParameter;
private boolean configuredByReverseMappingMethod = false;
public static Method forMethodRequiringImplementation(ExecutableElement executable, List<Parameter> parameters,
Type returnType, Map<String, List<Mapping>> mappings,
@ -150,6 +155,7 @@ public class Method {
public void setMappings(Map<String, List<Mapping>> mappings) {
this.mappings = mappings;
this.configuredByReverseMappingMethod = true;
}
public IterableMapping getIterableMapping() {
@ -158,6 +164,7 @@ public class Method {
public void setIterableMapping(IterableMapping iterableMapping) {
this.iterableMapping = iterableMapping;
this.configuredByReverseMappingMethod = true;
}
public MapMapping getMapMapping() {
@ -166,6 +173,7 @@ public class Method {
public void setMapMapping(MapMapping mapMapping) {
this.mapMapping = mapMapping;
this.configuredByReverseMappingMethod = true;
}
public boolean reverses(Method method) {
@ -188,6 +196,15 @@ public class Method {
&& getResultType().isMapType();
}
/**
* Whether this method is configured by itself or by the corresponding reverse mapping method.
*
* @return {@code true} if this method is configured by itself, {@code false} otherwise.
*/
public boolean isConfiguredByReverseMappingMethod() {
return configuredByReverseMappingMethod;
}
private boolean equals(Object o1, Object o2) {
return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( o2 );
}

View File

@ -27,7 +27,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.Messager;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
@ -377,7 +376,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
private boolean hasSourceProperty(Method method, String propertyName) {
for ( Parameter parameter : method.getSourceParameters() ) {
if ( hasProperty( parameter, propertyName ) ) {
if ( hasSourceProperty( parameter, propertyName ) ) {
return true;
}
}
@ -385,20 +384,21 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
return false;
}
private boolean hasProperty(Parameter parameter, String propertyName) {
private boolean hasSourceProperty(Parameter parameter, String propertyName) {
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
List<ExecutableElement> getters = filters.getterMethodsIn(
elementUtils.getAllMembers( parameterTypeElement )
);
targetAccessors.addAll(
filters.alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( parameterTypeElement )
)
);
return executables.getPropertyNames( targetAccessors ).contains( propertyName );
return executables.getPropertyNames( getters ).contains( propertyName );
}
private boolean reportErrorIfMappedPropertiesDontExist(Method method) {
// only report errors if this method itself is configured
if ( method.isConfiguredByReverseMappingMethod() ) {
return true;
}
TypeElement resultTypeElement = method.getResultType().getTypeElement();
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
elementUtils.getAllMembers( resultTypeElement )
@ -431,7 +431,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
foundUnmappedProperty = true;
}
else {
if ( !hasProperty( sourceParameter, mappedProperty.getSourcePropertyName() ) ) {
if ( !hasSourceProperty( sourceParameter, mappedProperty.getSourcePropertyName() ) ) {
messager.printMessage(
Kind.ERROR,
String.format(

View File

@ -55,4 +55,15 @@ public class OnewayTest extends MapperTestBase {
assertThat( source ).isNotNull();
assertThat( source.retrieveBar() ).isEqualTo( 23 );
}
@Test
@IssueKey("104")
public void shouldMapMappedAttributeWithoutSetterInSourceType() {
Source source = new Source();
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getQux() ).isEqualTo( 23L );
}
}

View File

@ -20,8 +20,9 @@ package org.mapstruct.ap.test.oneway;
public class Source {
private int foo = 42;
private final int foo = 42;
private int bar;
private final long qax = 23L;
public int getFoo() {
return foo;
@ -34,4 +35,8 @@ public class Source {
public int retrieveBar() {
return bar;
}
public long getQax() {
return qax;
}
}

View File

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

View File

@ -21,7 +21,8 @@ package org.mapstruct.ap.test.oneway;
public class Target {
private Long foo;
private int bar = 23;
private final int bar = 23;
private long qux;
public void setFoo(Long foo) {
this.foo = foo;
@ -34,4 +35,12 @@ public class Target {
public int getBar() {
return bar;
}
public void setQux(long qux) {
this.qux = qux;
}
public long getQux() {
return qux;
}
}