mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#92 The getter methods and setter methods contain pure getters and setters. A new method has been created to offer an alternative target accessors for Collection properties when setter is not available. The lists for this are kept separate.
This commit is contained in:
parent
e5cfb07af5
commit
6c2683a6f3
@ -53,7 +53,6 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
|
|||||||
private final boolean isEnumType;
|
private final boolean isEnumType;
|
||||||
private final boolean isIterableType;
|
private final boolean isIterableType;
|
||||||
private final boolean isCollectionType;
|
private final boolean isCollectionType;
|
||||||
private final boolean isListType;
|
|
||||||
private final boolean isMapType;
|
private final boolean isMapType;
|
||||||
private final Type implementationType;
|
private final Type implementationType;
|
||||||
private final TypeMirror typeMirror;
|
private final TypeMirror typeMirror;
|
||||||
@ -61,14 +60,13 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
|
|||||||
private final TypeElement typeElement;
|
private final TypeElement typeElement;
|
||||||
|
|
||||||
public Type(TypeMirror typeMirror, List<Type> typeParameters, Type implementationType, boolean isIterableType,
|
public Type(TypeMirror typeMirror, List<Type> typeParameters, Type implementationType, boolean isIterableType,
|
||||||
boolean isCollectionType, boolean isListType, boolean isMapType, Types typeUtils,
|
boolean isCollectionType, boolean isMapType, Types typeUtils,
|
||||||
Elements elementUtils) {
|
Elements elementUtils) {
|
||||||
this.typeMirror = typeMirror;
|
this.typeMirror = typeMirror;
|
||||||
this.implementationType = implementationType;
|
this.implementationType = implementationType;
|
||||||
this.typeParameters = typeParameters;
|
this.typeParameters = typeParameters;
|
||||||
this.isIterableType = isIterableType;
|
this.isIterableType = isIterableType;
|
||||||
this.isCollectionType = isCollectionType;
|
this.isCollectionType = isCollectionType;
|
||||||
this.isListType = isListType;
|
|
||||||
this.isMapType = isMapType;
|
this.isMapType = isMapType;
|
||||||
this.typeUtils = typeUtils;
|
this.typeUtils = typeUtils;
|
||||||
|
|
||||||
@ -152,10 +150,6 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
|
|||||||
return isCollectionType;
|
return isCollectionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isListType() {
|
|
||||||
return isListType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMapType() {
|
public boolean isMapType() {
|
||||||
return isMapType;
|
return isMapType;
|
||||||
}
|
}
|
||||||
|
@ -284,19 +284,22 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
}
|
}
|
||||||
|
|
||||||
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
||||||
List<ExecutableElement> targetSetters = filters.setterMethodsIn(
|
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
||||||
elementUtils.getAllMembers( resultTypeElement )
|
elementUtils.getAllMembers( resultTypeElement )
|
||||||
);
|
);
|
||||||
|
targetAccessors.addAll( filters.alternativeTargetAccessorMethodsIn(
|
||||||
|
elementUtils.getAllMembers( resultTypeElement ) )
|
||||||
|
);
|
||||||
|
|
||||||
for ( ExecutableElement setterMethod : targetSetters ) {
|
for ( ExecutableElement targetAccessor : targetAccessors ) {
|
||||||
String targetPropertyName = executables.getPropertyName( setterMethod );
|
String targetPropertyName = executables.getPropertyName( targetAccessor );
|
||||||
|
|
||||||
Mapping mapping = method.getMapping( targetPropertyName );
|
Mapping mapping = method.getMapping( targetPropertyName );
|
||||||
|
|
||||||
PropertyMapping propertyMapping = null;
|
PropertyMapping propertyMapping = null;
|
||||||
if ( mapping != null && mapping.getSourceParameterName() != null ) {
|
if ( mapping != null && mapping.getSourceParameterName() != null ) {
|
||||||
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
|
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
|
||||||
propertyMapping = getPropertyMapping( methods, method, setterMethod, parameter );
|
propertyMapping = getPropertyMapping( methods, method, targetAccessor, parameter );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( propertyMapping == null ) {
|
if ( propertyMapping == null ) {
|
||||||
@ -304,7 +307,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
PropertyMapping newPropertyMapping = getPropertyMapping(
|
PropertyMapping newPropertyMapping = getPropertyMapping(
|
||||||
methods,
|
methods,
|
||||||
method,
|
method,
|
||||||
setterMethod,
|
targetAccessor,
|
||||||
sourceParameter
|
sourceParameter
|
||||||
);
|
);
|
||||||
if ( propertyMapping != null && newPropertyMapping != null ) {
|
if ( propertyMapping != null && newPropertyMapping != null ) {
|
||||||
@ -327,7 +330,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> targetProperties = executables.getPropertyNames( targetSetters );
|
Set<String> targetProperties = executables.getPropertyNames( targetAccessors );
|
||||||
|
|
||||||
reportErrorForUnmappedTargetPropertiesIfRequired(
|
reportErrorForUnmappedTargetPropertiesIfRequired(
|
||||||
method,
|
method,
|
||||||
@ -380,20 +383,24 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
|||||||
|
|
||||||
private boolean hasProperty(Parameter parameter, String propertyName) {
|
private boolean hasProperty(Parameter parameter, String propertyName) {
|
||||||
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
|
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
|
||||||
List<ExecutableElement> getters = filters.setterMethodsIn(
|
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
||||||
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) {
|
||||||
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
TypeElement resultTypeElement = method.getResultType().getTypeElement();
|
||||||
List<ExecutableElement> targetSetters = filters.setterMethodsIn(
|
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
|
||||||
elementUtils.getAllMembers( resultTypeElement )
|
elementUtils.getAllMembers( resultTypeElement )
|
||||||
);
|
);
|
||||||
|
targetAccessors.addAll( filters.alternativeTargetAccessorMethodsIn(
|
||||||
Set<String> targetProperties = executables.getPropertyNames( targetSetters );
|
elementUtils.getAllMembers( resultTypeElement ) )
|
||||||
|
);
|
||||||
|
Set<String> targetProperties = executables.getPropertyNames( targetAccessors );
|
||||||
|
|
||||||
boolean foundUnmappedProperty = false;
|
boolean foundUnmappedProperty = false;
|
||||||
|
|
||||||
|
@ -52,17 +52,29 @@ public class Filters {
|
|||||||
|
|
||||||
public List<ExecutableElement> setterMethodsIn(Iterable<? extends Element> elements) {
|
public List<ExecutableElement> setterMethodsIn(Iterable<? extends Element> elements) {
|
||||||
List<ExecutableElement> setterMethods = new LinkedList<ExecutableElement>();
|
List<ExecutableElement> setterMethods = new LinkedList<ExecutableElement>();
|
||||||
List<ExecutableElement> getterMethods = new LinkedList<ExecutableElement>();
|
|
||||||
|
|
||||||
for ( ExecutableElement method : methodsIn( elements ) ) {
|
for ( ExecutableElement method : methodsIn( elements ) ) {
|
||||||
if ( executables.isSetterMethod( method ) ) {
|
if ( executables.isSetterMethod( method ) ) {
|
||||||
setterMethods.add( method );
|
setterMethods.add( method );
|
||||||
}
|
}
|
||||||
else if ( executables.isGetterMethod( method ) ) {
|
|
||||||
getterMethods.add( method );
|
|
||||||
}
|
}
|
||||||
|
return setterMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A getter could be an alternative target-accessor if a setter is not available, and the
|
||||||
|
* target is a collection.
|
||||||
|
*
|
||||||
|
* Provided such a getter is initialized lazy by the target class, e.g. in generated JAXB beans.
|
||||||
|
*
|
||||||
|
* @param elements
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<ExecutableElement> alternativeTargetAccessorMethodsIn(Iterable<? extends Element> elements) {
|
||||||
|
List<ExecutableElement> setterMethods = setterMethodsIn( elements );
|
||||||
|
List<ExecutableElement> getterMethods = getterMethodsIn( elements );
|
||||||
|
List<ExecutableElement> alternativeTargetAccessorsMethods = new LinkedList<ExecutableElement>();
|
||||||
|
|
||||||
if (getterMethods.size() > setterMethods.size()) {
|
if (getterMethods.size() > setterMethods.size()) {
|
||||||
// there could be a getter method for a list that is not present as setter.
|
// there could be a getter method for a list that is not present as setter.
|
||||||
// a getter could substitue the setter in that case and act as setter.
|
// a getter could substitue the setter in that case and act as setter.
|
||||||
@ -77,12 +89,12 @@ public class Filters {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !matchFound && executables.retrieveReturnType( getterMethod ).isListType() ) {
|
if ( !matchFound && executables.retrieveReturnType( getterMethod ).isCollectionType() ) {
|
||||||
setterMethods.add( getterMethod );
|
alternativeTargetAccessorsMethods.add( getterMethod );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return setterMethods;
|
return alternativeTargetAccessorsMethods;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,10 +117,6 @@ public class TypeFactory {
|
|||||||
mirror,
|
mirror,
|
||||||
collectionType
|
collectionType
|
||||||
);
|
);
|
||||||
boolean isListType = typeUtils.isSubtype(
|
|
||||||
mirror,
|
|
||||||
listType
|
|
||||||
);
|
|
||||||
boolean isMapType = typeUtils.isSubtype(
|
boolean isMapType = typeUtils.isSubtype(
|
||||||
mirror,
|
mirror,
|
||||||
mapType
|
mapType
|
||||||
@ -132,7 +128,6 @@ public class TypeFactory {
|
|||||||
implementationType,
|
implementationType,
|
||||||
isIterableType,
|
isIterableType,
|
||||||
isCollectionType,
|
isCollectionType,
|
||||||
isListType,
|
|
||||||
isMapType,
|
isMapType,
|
||||||
typeUtils,
|
typeUtils,
|
||||||
elementUtils
|
elementUtils
|
||||||
@ -188,7 +183,6 @@ public class TypeFactory {
|
|||||||
null,
|
null,
|
||||||
implementationType.isIterableType(),
|
implementationType.isIterableType(),
|
||||||
implementationType.isCollectionType(),
|
implementationType.isCollectionType(),
|
||||||
implementationType.isListType(),
|
|
||||||
implementationType.isMapType(),
|
implementationType.isMapType(),
|
||||||
typeUtils,
|
typeUtils,
|
||||||
elementUtils
|
elementUtils
|
||||||
|
@ -71,7 +71,7 @@ public class CollectionMappingTest extends MapperTestBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@IssueKey("6")
|
@IssueKey("92")
|
||||||
public void shouldMapListWithoutSetter() {
|
public void shouldMapListWithoutSetter() {
|
||||||
Source source = new Source();
|
Source source = new Source();
|
||||||
source.setStringList2( Arrays.asList( "Bob", "Alice" ) );
|
source.setStringList2( Arrays.asList( "Bob", "Alice" ) );
|
||||||
|
@ -171,7 +171,7 @@ public class DefaultCollectionImplementationTest extends MapperTestBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@IssueKey("6")
|
@IssueKey("92")
|
||||||
public void shouldUseDefaultImplementationForListWithoutSetter() {
|
public void shouldUseDefaultImplementationForListWithoutSetter() {
|
||||||
Source source = new Source();
|
Source source = new Source();
|
||||||
source.setFooList( createSourceFooList() );
|
source.setFooList( createSourceFooList() );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user