From c281711aaa05775d3bd9239b0b9b8245703e413c Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Sun, 26 Jan 2014 11:36:34 +0100 Subject: [PATCH] #109 Removing package cycle between model and util --- .../ap/conversion/ConversionProvider.java | 2 +- .../mapstruct/ap/conversion/Conversions.java | 3 +- .../conversion/DefaultConversionContext.java | 2 +- .../ap/model/DefaultMapperReference.java | 1 - .../java/org/mapstruct/ap/model/Mapper.java | 2 - .../java/org/mapstruct/ap/model/Type.java | 3 +- .../ap/{util => model}/TypeFactory.java | 46 +++++++++++++++- ...nnotationBasedComponentModelProcessor.java | 2 +- .../DefaultModelElementProcessorContext.java | 2 +- .../ap/processor/MapperCreationProcessor.java | 53 ++++++++++++++++--- .../processor/MethodRetrievalProcessor.java | 13 ++--- .../ap/processor/ModelElementProcessor.java | 2 +- .../org/mapstruct/ap/util/Executables.java | 52 +----------------- .../java/org/mapstruct/ap/util/Filters.java | 43 ++------------- 14 files changed, 110 insertions(+), 116 deletions(-) rename processor/src/main/java/org/mapstruct/ap/{util => model}/TypeFactory.java (84%) diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/ConversionProvider.java b/processor/src/main/java/org/mapstruct/ap/conversion/ConversionProvider.java index 0321c0b25..a5e8bc4c7 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/ConversionProvider.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/ConversionProvider.java @@ -22,7 +22,7 @@ import java.util.Date; import org.mapstruct.ap.model.Type; import org.mapstruct.ap.model.TypeConversion; -import org.mapstruct.ap.util.TypeFactory; +import org.mapstruct.ap.model.TypeFactory; /** * Implementations create inline {@link TypeConversion}s such as diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java index f29a18e7e..1e47a1c9b 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/Conversions.java @@ -23,10 +23,11 @@ import java.math.BigInteger; import java.util.Date; import java.util.HashMap; import java.util.Map; + import javax.lang.model.util.Elements; import org.mapstruct.ap.model.Type; -import org.mapstruct.ap.util.TypeFactory; +import org.mapstruct.ap.model.TypeFactory; import static org.mapstruct.ap.conversion.ReverseConversion.reverse; diff --git a/processor/src/main/java/org/mapstruct/ap/conversion/DefaultConversionContext.java b/processor/src/main/java/org/mapstruct/ap/conversion/DefaultConversionContext.java index 317889ebf..8e251db5a 100644 --- a/processor/src/main/java/org/mapstruct/ap/conversion/DefaultConversionContext.java +++ b/processor/src/main/java/org/mapstruct/ap/conversion/DefaultConversionContext.java @@ -20,7 +20,7 @@ package org.mapstruct.ap.conversion; import org.mapstruct.ap.conversion.ConversionProvider.Context; import org.mapstruct.ap.model.Type; -import org.mapstruct.ap.util.TypeFactory; +import org.mapstruct.ap.model.TypeFactory; /** * Default implementation of the {@link Context} passed to conversion providers. diff --git a/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java b/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java index 98c942362..a5ac8c8f5 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java +++ b/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java @@ -23,7 +23,6 @@ import java.util.Set; import org.mapstruct.ap.util.Collections; import org.mapstruct.ap.util.Strings; -import org.mapstruct.ap.util.TypeFactory; /** * Mapper reference which is retrieved via the {@code Mappers#getMapper()} method. Used by default if no other component diff --git a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java index 355b00a60..d825ad78f 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java @@ -29,8 +29,6 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; -import org.mapstruct.ap.util.TypeFactory; - /** * Represents a type implementing a mapper interface (annotated with {@code @Mapper}). This is the root object of the * mapper model. diff --git a/processor/src/main/java/org/mapstruct/ap/model/Type.java b/processor/src/main/java/org/mapstruct/ap/model/Type.java index 114350bcd..751ec5ce8 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Type.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.model; import java.util.Collections; import java.util.List; import java.util.Set; + import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Name; @@ -32,8 +33,6 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.SimpleElementVisitor6; import javax.lang.model.util.Types; -import org.mapstruct.ap.util.TypeFactory; - /** * Represents the type of a bean property, parameter etc. Each type corresponds to a {@link TypeMirror}, i.e. there are * different instances for e.g. {@code Set} and {@code Set}. diff --git a/processor/src/main/java/org/mapstruct/ap/util/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/model/TypeFactory.java similarity index 84% rename from processor/src/main/java/org/mapstruct/ap/util/TypeFactory.java rename to processor/src/main/java/org/mapstruct/ap/model/TypeFactory.java index 728c0ad76..cfe9b745f 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/model/TypeFactory.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.mapstruct.ap.util; +package org.mapstruct.ap.model; import java.util.ArrayList; import java.util.Collection; @@ -35,7 +35,10 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentNavigableMap; import java.util.concurrent.ConcurrentSkipListMap; + +import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -43,7 +46,7 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import org.mapstruct.ap.AnnotationProcessingException; -import org.mapstruct.ap.model.Type; +import org.mapstruct.ap.MappingTargetPrism; /** * Factory creating {@link Type} instances. @@ -132,6 +135,45 @@ public class TypeFactory { ); } + public Parameter getSingleParameter(ExecutableElement method) { + List parameters = method.getParameters(); + + if ( parameters.size() != 1 ) { + //TODO: Log error + return null; + } + + VariableElement parameter = parameters.get( 0 ); + + return new Parameter( + parameter.getSimpleName().toString(), + getType( parameter.asType() ), + false + ); + } + + public List getParameters(ExecutableElement method) { + List parameters = method.getParameters(); + List result = new ArrayList( parameters.size() ); + + for ( VariableElement parameter : parameters ) { + result + .add( + new Parameter( + parameter.getSimpleName().toString(), + getType( parameter.asType() ), + MappingTargetPrism.getInstanceOn( parameter ) != null + ) + ); + } + + return result; + } + + public Type getReturnType(ExecutableElement method) { + return getType( method.getReturnType() ); + } + private List getTypeParameters(TypeMirror mirror) { if ( mirror.getKind() != TypeKind.DECLARED ) { return java.util.Collections.emptyList(); diff --git a/processor/src/main/java/org/mapstruct/ap/processor/AnnotationBasedComponentModelProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/AnnotationBasedComponentModelProcessor.java index 269b9be85..894e9bfbf 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/AnnotationBasedComponentModelProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/AnnotationBasedComponentModelProcessor.java @@ -27,8 +27,8 @@ import org.mapstruct.ap.model.Annotation; import org.mapstruct.ap.model.AnnotationMapperReference; import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.MapperReference; +import org.mapstruct.ap.model.TypeFactory; import org.mapstruct.ap.option.OptionsHelper; -import org.mapstruct.ap.util.TypeFactory; /** * An {@link ModelElementProcessor} which converts the given {@link Mapper} diff --git a/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java b/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java index 0eb9442e4..3764f1368 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/DefaultModelElementProcessorContext.java @@ -28,8 +28,8 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; +import org.mapstruct.ap.model.TypeFactory; import org.mapstruct.ap.option.Options; -import org.mapstruct.ap.util.TypeFactory; /** * Default implementation of the processor context. diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index b5652eb33..103bdcc14 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Set; import javax.annotation.processing.Messager; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; @@ -56,6 +57,7 @@ import org.mapstruct.ap.model.Parameter; import org.mapstruct.ap.model.PropertyMapping; import org.mapstruct.ap.model.Type; import org.mapstruct.ap.model.TypeConversion; +import org.mapstruct.ap.model.TypeFactory; import org.mapstruct.ap.model.source.Mapping; import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.MethodMatcher; @@ -64,7 +66,6 @@ import org.mapstruct.ap.option.ReportingPolicy; import org.mapstruct.ap.util.Executables; import org.mapstruct.ap.util.Filters; import org.mapstruct.ap.util.Strings; -import org.mapstruct.ap.util.TypeFactory; /** * A {@link ModelElementProcessor} which creates a {@link Mapper} from the given @@ -93,7 +94,7 @@ public class MapperCreationProcessor implements ModelElementProcessor methods, Method method, Parameter parameter, ExecutableElement sourceAccessor, ExecutableElement targetAcessor, String dateFormat) { - Type sourceType = executables.retrieveReturnType( sourceAccessor ); + Type sourceType = typeFactory.getReturnType( sourceAccessor ); Type targetType = null; String conversionString = null; conversionString = parameter.getName() + "." + sourceAccessor.getSimpleName().toString() + "()"; if ( executables.isSetterMethod( targetAcessor ) ) { - targetType = executables.retrieveSingleParameter( targetAcessor ).getType(); + targetType = typeFactory.getSingleParameter( targetAcessor ).getType(); } else if ( executables.isGetterMethod( targetAcessor ) ) { - targetType = executables.retrieveReturnType( targetAcessor ); + targetType = typeFactory.getReturnType( targetAcessor ); } MappingMethodReference propertyMappingMethod = getMappingMethodReference( methods, sourceType, targetType ); @@ -786,4 +787,42 @@ public class MapperCreationProcessor implements ModelElementProcessor alternativeTargetAccessorMethodsIn(Iterable elements) { + List setterMethods = filters.setterMethodsIn( elements ); + List getterMethods = filters.getterMethodsIn( elements ); + List alternativeTargetAccessorsMethods = new LinkedList(); + + if ( getterMethods.size() > setterMethods.size() ) { + // there could be a getter method for a list that is not present as setter. + // a getter could substitute the setter in that case and act as setter. + // (assuming it is initialized) + for ( ExecutableElement getterMethod : getterMethods ) { + boolean matchFound = false; + String getterPropertyName = executables.getPropertyName( getterMethod ); + for ( ExecutableElement setterMethod : setterMethods ) { + String setterPropertyName = executables.getPropertyName( setterMethod ); + if ( getterPropertyName.equals( setterPropertyName ) ) { + matchFound = true; + break; + } + } + if ( !matchFound && typeFactory.getReturnType( getterMethod ).isCollectionType() ) { + alternativeTargetAccessorsMethods.add( getterMethod ); + } + } + } + + return alternativeTargetAccessorsMethods; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java index 86506e3ea..b6d5d61ae 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MethodRetrievalProcessor.java @@ -18,10 +18,13 @@ */ package org.mapstruct.ap.processor; +import static javax.lang.model.util.ElementFilter.methodsIn; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.annotation.processing.Messager; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; @@ -39,14 +42,12 @@ import org.mapstruct.ap.MappingPrism; import org.mapstruct.ap.MappingsPrism; import org.mapstruct.ap.model.Parameter; import org.mapstruct.ap.model.Type; +import org.mapstruct.ap.model.TypeFactory; import org.mapstruct.ap.model.source.IterableMapping; import org.mapstruct.ap.model.source.MapMapping; import org.mapstruct.ap.model.source.Mapping; import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.util.Executables; -import org.mapstruct.ap.util.TypeFactory; - -import static javax.lang.model.util.ElementFilter.methodsIn; /** * A {@link ModelElementProcessor} which retrieves a list of {@link Method}s @@ -66,7 +67,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor process(ProcessorContext context, TypeElement mapperTypeElement, Void sourceModel) { this.messager = context.getMessager(); this.typeFactory = context.getTypeFactory(); - this.executables = new Executables( typeFactory ); + this.executables = new Executables(); return retrieveMethods( mapperTypeElement, true ); } @@ -119,8 +120,8 @@ public class MethodRetrievalProcessor implements ModelElementProcessor parameters = executables.retrieveParameters( method ); - Type returnType = executables.retrieveReturnType( method ); + List parameters = typeFactory.getParameters( method ); + Type returnType = typeFactory.getReturnType( method ); //add method with property mappings if an implementation needs to be generated boolean methodRequiresImplementation = method.getModifiers().contains( Modifier.ABSTRACT ); diff --git a/processor/src/main/java/org/mapstruct/ap/processor/ModelElementProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/ModelElementProcessor.java index 508cffc8b..5f58635dc 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/ModelElementProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/ModelElementProcessor.java @@ -25,8 +25,8 @@ import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; +import org.mapstruct.ap.model.TypeFactory; import org.mapstruct.ap.option.Options; -import org.mapstruct.ap.util.TypeFactory; /** * A processor which performs one task of the mapper generation, e.g. retrieving diff --git a/processor/src/main/java/org/mapstruct/ap/util/Executables.java b/processor/src/main/java/org/mapstruct/ap/util/Executables.java index fd95cebe5..9975e06b4 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/Executables.java +++ b/processor/src/main/java/org/mapstruct/ap/util/Executables.java @@ -19,19 +19,14 @@ package org.mapstruct.ap.util; import java.beans.Introspector; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; + import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; -import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; -import org.mapstruct.ap.MappingTargetPrism; -import org.mapstruct.ap.model.Parameter; -import org.mapstruct.ap.model.Type; - /** * Provides functionality around {@link ExecutableElement}s. * @@ -39,10 +34,7 @@ import org.mapstruct.ap.model.Type; */ public class Executables { - private final TypeFactory typeFactory; - - public Executables(TypeFactory typeFactory) { - this.typeFactory = typeFactory; + public Executables() { } public boolean isGetterMethod(ExecutableElement method) { @@ -111,44 +103,4 @@ public class Executables { return propertyNames; } - - public Parameter retrieveSingleParameter(ExecutableElement method) { - List parameters = method.getParameters(); - - if ( parameters.size() != 1 ) { - //TODO: Log error - return null; - } - - VariableElement parameter = parameters.get( 0 ); - - return new Parameter( - parameter.getSimpleName().toString(), - typeFactory.getType( parameter.asType() ), - false - ); - } - - public List retrieveParameters(ExecutableElement method) { - List parameters = method.getParameters(); - List result = new ArrayList( parameters.size() ); - - for ( VariableElement parameter : parameters ) { - result - .add( - new Parameter( - parameter.getSimpleName().toString(), - typeFactory.getType( parameter.asType() ), - MappingTargetPrism.getInstanceOn( parameter ) != null - ) - ); - } - - return result; - } - - public Type retrieveReturnType(ExecutableElement method) { - return typeFactory.getType( method.getReturnType() ); - } - } diff --git a/processor/src/main/java/org/mapstruct/ap/util/Filters.java b/processor/src/main/java/org/mapstruct/ap/util/Filters.java index cb3776254..1121ab586 100644 --- a/processor/src/main/java/org/mapstruct/ap/util/Filters.java +++ b/processor/src/main/java/org/mapstruct/ap/util/Filters.java @@ -18,13 +18,14 @@ */ package org.mapstruct.ap.util; +import static javax.lang.model.util.ElementFilter.methodsIn; + import java.util.LinkedList; import java.util.List; + import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import static javax.lang.model.util.ElementFilter.methodsIn; - /** * Filter methods for working with {@link Element} collections. * @@ -60,42 +61,4 @@ public class Filters { } 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 alternativeTargetAccessorMethodsIn(Iterable elements) { - List setterMethods = setterMethodsIn( elements ); - List getterMethods = getterMethodsIn( elements ); - List alternativeTargetAccessorsMethods = new LinkedList(); - - if ( getterMethods.size() > setterMethods.size() ) { - // there could be a getter method for a list that is not present as setter. - // a getter could substitute the setter in that case and act as setter. - // (assuming it is initialized) - for ( ExecutableElement getterMethod : getterMethods ) { - boolean matchFound = false; - String getterPropertyName = executables.getPropertyName( getterMethod ); - for ( ExecutableElement setterMethod : setterMethods ) { - String setterPropertyName = executables.getPropertyName( setterMethod ); - if ( getterPropertyName.equals( setterPropertyName ) ) { - matchFound = true; - break; - } - } - if ( !matchFound && executables.retrieveReturnType( getterMethod ).isCollectionType() ) { - alternativeTargetAccessorsMethods.add( getterMethod ); - } - } - } - - return alternativeTargetAccessorsMethods; - } }