mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#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:
parent
196d91324a
commit
5dd3ab2bec
@ -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 );
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user