#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 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;
} }

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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

View File

@ -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" ) );

View File

@ -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() );