#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:
sjaakd 2014-01-16 20:57:28 +01:00 committed by Gunnar Morling
parent e5cfb07af5
commit 6c2683a6f3
6 changed files with 41 additions and 34 deletions

View File

@ -53,7 +53,6 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
private final boolean isEnumType;
private final boolean isIterableType;
private final boolean isCollectionType;
private final boolean isListType;
private final boolean isMapType;
private final Type implementationType;
private final TypeMirror typeMirror;
@ -61,14 +60,13 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
private final TypeElement typeElement;
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) {
this.typeMirror = typeMirror;
this.implementationType = implementationType;
this.typeParameters = typeParameters;
this.isIterableType = isIterableType;
this.isCollectionType = isCollectionType;
this.isListType = isListType;
this.isMapType = isMapType;
this.typeUtils = typeUtils;
@ -152,10 +150,6 @@ public class Type extends AbstractModelElement implements Comparable<Type> {
return isCollectionType;
}
public boolean isListType() {
return isListType;
}
public boolean isMapType() {
return isMapType;
}

View File

@ -284,19 +284,22 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
}
TypeElement resultTypeElement = method.getResultType().getTypeElement();
List<ExecutableElement> targetSetters = filters.setterMethodsIn(
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
elementUtils.getAllMembers( resultTypeElement )
);
targetAccessors.addAll( filters.alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( resultTypeElement ) )
);
for ( ExecutableElement setterMethod : targetSetters ) {
String targetPropertyName = executables.getPropertyName( setterMethod );
for ( ExecutableElement targetAccessor : targetAccessors ) {
String targetPropertyName = executables.getPropertyName( targetAccessor );
Mapping mapping = method.getMapping( targetPropertyName );
PropertyMapping propertyMapping = null;
if ( mapping != null && mapping.getSourceParameterName() != null ) {
Parameter parameter = method.getSourceParameter( mapping.getSourceParameterName() );
propertyMapping = getPropertyMapping( methods, method, setterMethod, parameter );
propertyMapping = getPropertyMapping( methods, method, targetAccessor, parameter );
}
if ( propertyMapping == null ) {
@ -304,7 +307,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
PropertyMapping newPropertyMapping = getPropertyMapping(
methods,
method,
setterMethod,
targetAccessor,
sourceParameter
);
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(
method,
@ -380,20 +383,24 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
private boolean hasProperty(Parameter parameter, String propertyName) {
TypeElement parameterTypeElement = parameter.getType().getTypeElement();
List<ExecutableElement> getters = filters.setterMethodsIn(
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
elementUtils.getAllMembers( parameterTypeElement )
);
return executables.getPropertyNames( getters ).contains( propertyName );
targetAccessors.addAll( filters.alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( parameterTypeElement ) )
);
return executables.getPropertyNames( targetAccessors ).contains( propertyName );
}
private boolean reportErrorIfMappedPropertiesDontExist(Method method) {
TypeElement resultTypeElement = method.getResultType().getTypeElement();
List<ExecutableElement> targetSetters = filters.setterMethodsIn(
List<ExecutableElement> targetAccessors = filters.setterMethodsIn(
elementUtils.getAllMembers( resultTypeElement )
);
Set<String> targetProperties = executables.getPropertyNames( targetSetters );
targetAccessors.addAll( filters.alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( resultTypeElement ) )
);
Set<String> targetProperties = executables.getPropertyNames( targetAccessors );
boolean foundUnmappedProperty = false;

View File

@ -52,16 +52,28 @@ public class Filters {
public List<ExecutableElement> setterMethodsIn(Iterable<? extends Element> elements) {
List<ExecutableElement> setterMethods = new LinkedList<ExecutableElement>();
List<ExecutableElement> getterMethods = new LinkedList<ExecutableElement>();
for ( ExecutableElement method : methodsIn( elements ) ) {
if ( executables.isSetterMethod( 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()) {
// there could be a getter method for a list that is not present as setter.
@ -77,12 +89,12 @@ public class Filters {
break;
}
}
if ( !matchFound && executables.retrieveReturnType( getterMethod ).isListType() ) {
setterMethods.add( getterMethod );
if ( !matchFound && executables.retrieveReturnType( getterMethod ).isCollectionType() ) {
alternativeTargetAccessorsMethods.add( getterMethod );
}
}
}
return setterMethods;
return alternativeTargetAccessorsMethods;
}
}

View File

@ -117,10 +117,6 @@ public class TypeFactory {
mirror,
collectionType
);
boolean isListType = typeUtils.isSubtype(
mirror,
listType
);
boolean isMapType = typeUtils.isSubtype(
mirror,
mapType
@ -132,7 +128,6 @@ public class TypeFactory {
implementationType,
isIterableType,
isCollectionType,
isListType,
isMapType,
typeUtils,
elementUtils
@ -188,7 +183,6 @@ public class TypeFactory {
null,
implementationType.isIterableType(),
implementationType.isCollectionType(),
implementationType.isListType(),
implementationType.isMapType(),
typeUtils,
elementUtils

View File

@ -71,7 +71,7 @@ public class CollectionMappingTest extends MapperTestBase {
}
@Test
@IssueKey("6")
@IssueKey("92")
public void shouldMapListWithoutSetter() {
Source source = new Source();
source.setStringList2( Arrays.asList( "Bob", "Alice" ) );

View File

@ -171,7 +171,7 @@ public class DefaultCollectionImplementationTest extends MapperTestBase {
}
@Test
@IssueKey("6")
@IssueKey("92")
public void shouldUseDefaultImplementationForListWithoutSetter() {
Source source = new Source();
source.setFooList( createSourceFooList() );