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
|
* Represents a mapping method with source and target type and the mappings between the properties of source and target
|
||||||
* type.
|
* 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
|
* @author Gunnar Morling
|
||||||
*/
|
*/
|
||||||
@ -40,13 +44,14 @@ public class Method {
|
|||||||
private final Type declaringMapper;
|
private final Type declaringMapper;
|
||||||
private final ExecutableElement executable;
|
private final ExecutableElement executable;
|
||||||
private final List<Parameter> parameters;
|
private final List<Parameter> parameters;
|
||||||
|
private final Parameter targetParameter;
|
||||||
private final Type returnType;
|
private final Type returnType;
|
||||||
|
|
||||||
private Map<String, List<Mapping>> mappings;
|
private Map<String, List<Mapping>> mappings;
|
||||||
private IterableMapping iterableMapping;
|
private IterableMapping iterableMapping;
|
||||||
private MapMapping mapMapping;
|
private MapMapping mapMapping;
|
||||||
|
|
||||||
private final Parameter targetParameter;
|
private boolean configuredByReverseMappingMethod = false;
|
||||||
|
|
||||||
public static Method forMethodRequiringImplementation(ExecutableElement executable, List<Parameter> parameters,
|
public static Method forMethodRequiringImplementation(ExecutableElement executable, List<Parameter> parameters,
|
||||||
Type returnType, Map<String, List<Mapping>> mappings,
|
Type returnType, Map<String, List<Mapping>> mappings,
|
||||||
@ -150,6 +155,7 @@ public class Method {
|
|||||||
|
|
||||||
public void setMappings(Map<String, List<Mapping>> mappings) {
|
public void setMappings(Map<String, List<Mapping>> mappings) {
|
||||||
this.mappings = mappings;
|
this.mappings = mappings;
|
||||||
|
this.configuredByReverseMappingMethod = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IterableMapping getIterableMapping() {
|
public IterableMapping getIterableMapping() {
|
||||||
@ -158,6 +164,7 @@ public class Method {
|
|||||||
|
|
||||||
public void setIterableMapping(IterableMapping iterableMapping) {
|
public void setIterableMapping(IterableMapping iterableMapping) {
|
||||||
this.iterableMapping = iterableMapping;
|
this.iterableMapping = iterableMapping;
|
||||||
|
this.configuredByReverseMappingMethod = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MapMapping getMapMapping() {
|
public MapMapping getMapMapping() {
|
||||||
@ -166,6 +173,7 @@ public class Method {
|
|||||||
|
|
||||||
public void setMapMapping(MapMapping mapMapping) {
|
public void setMapMapping(MapMapping mapMapping) {
|
||||||
this.mapMapping = mapMapping;
|
this.mapMapping = mapMapping;
|
||||||
|
this.configuredByReverseMappingMethod = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reverses(Method method) {
|
public boolean reverses(Method method) {
|
||||||
@ -188,6 +196,15 @@ public class Method {
|
|||||||
&& getResultType().isMapType();
|
&& 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) {
|
private boolean equals(Object o1, Object o2) {
|
||||||
return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( 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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.processing.Messager;
|
import javax.annotation.processing.Messager;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
@ -377,7 +376,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
|
|
||||||
private boolean hasSourceProperty(Method method, String propertyName) {
|
private boolean hasSourceProperty(Method method, String propertyName) {
|
||||||
for ( Parameter parameter : method.getSourceParameters() ) {
|
for ( Parameter parameter : method.getSourceParameters() ) {
|
||||||
if ( hasProperty( parameter, propertyName ) ) {
|
if ( hasSourceProperty( parameter, propertyName ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,20 +384,21 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasProperty(Parameter parameter, String propertyName) {
|
private boolean hasSourceProperty(Parameter parameter, String propertyName) {
|
||||||
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
|
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
|
||||||
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
List<ExecutableElement> getters = filters.getterMethodsIn(
|
||||||
elementUtils.getAllMembers( parameterTypeElement )
|
elementUtils.getAllMembers( parameterTypeElement )
|
||||||
);
|
);
|
||||||
targetAccessors.addAll(
|
|
||||||
filters.alternativeTargetAccessorMethodsIn(
|
return executables.getPropertyNames( getters ).contains( propertyName );
|
||||||
elementUtils.getAllMembers( parameterTypeElement )
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return executables.getPropertyNames( targetAccessors ).contains( propertyName );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean reportErrorIfMappedPropertiesDontExist(Method method) {
|
private boolean reportErrorIfMappedPropertiesDontExist(Method method) {
|
||||||
|
// only report errors if this method itself is configured
|
||||||
|
if ( method.isConfiguredByReverseMappingMethod() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
||||||
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
||||||
elementUtils.getAllMembers( resultTypeElement )
|
elementUtils.getAllMembers( resultTypeElement )
|
||||||
@ -431,7 +431,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
foundUnmappedProperty = true;
|
foundUnmappedProperty = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( !hasProperty( sourceParameter, mappedProperty.getSourcePropertyName() ) ) {
|
if ( !hasSourceProperty( sourceParameter, mappedProperty.getSourcePropertyName() ) ) {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
Kind.ERROR,
|
Kind.ERROR,
|
||||||
String.format(
|
String.format(
|
||||||
|
@ -55,4 +55,15 @@ public class OnewayTest extends MapperTestBase {
|
|||||||
assertThat( source ).isNotNull();
|
assertThat( source ).isNotNull();
|
||||||
assertThat( source.retrieveBar() ).isEqualTo( 23 );
|
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 {
|
public class Source {
|
||||||
|
|
||||||
private int foo = 42;
|
private final int foo = 42;
|
||||||
private int bar;
|
private int bar;
|
||||||
|
private final long qax = 23L;
|
||||||
|
|
||||||
public int getFoo() {
|
public int getFoo() {
|
||||||
return foo;
|
return foo;
|
||||||
@ -34,4 +35,8 @@ public class Source {
|
|||||||
public int retrieveBar() {
|
public int retrieveBar() {
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getQax() {
|
||||||
|
return qax;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.mapstruct.ap.test.oneway;
|
package org.mapstruct.ap.test.oneway;
|
||||||
|
|
||||||
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 = "qax", target = "qux")
|
||||||
Target sourceToTarget(Source source);
|
Target sourceToTarget(Source source);
|
||||||
|
|
||||||
Source targetToSource(Target target);
|
Source targetToSource(Target target);
|
||||||
|
@ -21,7 +21,8 @@ package org.mapstruct.ap.test.oneway;
|
|||||||
public class Target {
|
public class Target {
|
||||||
|
|
||||||
private Long foo;
|
private Long foo;
|
||||||
private int bar = 23;
|
private final int bar = 23;
|
||||||
|
private long qux;
|
||||||
|
|
||||||
public void setFoo(Long foo) {
|
public void setFoo(Long foo) {
|
||||||
this.foo = foo;
|
this.foo = foo;
|
||||||
@ -34,4 +35,12 @@ public class Target {
|
|||||||
public int getBar() {
|
public int getBar() {
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setQux(long qux) {
|
||||||
|
this.qux = qux;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getQux() {
|
||||||
|
return qux;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user