#109 Removing package cycle between model and util

This commit is contained in:
Gunnar Morling 2014-01-26 11:36:34 +01:00
parent cbccdd847c
commit c281711aaa
14 changed files with 110 additions and 116 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<String>} and {@code Set<Integer>}.

View File

@ -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<? extends VariableElement> 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<Parameter> getParameters(ExecutableElement method) {
List<? extends VariableElement> parameters = method.getParameters();
List<Parameter> result = new ArrayList<Parameter>( 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<Type> getTypeParameters(TypeMirror mirror) {
if ( mirror.getKind() != TypeKind.DECLARED ) {
return java.util.Collections.emptyList();

View File

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

View File

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

View File

@ -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<List<Metho
this.typeFactory = context.getTypeFactory();
this.conversions = new Conversions( elementUtils, typeFactory );
this.executables = new Executables( typeFactory );
this.executables = new Executables();
this.filters = new Filters( executables );
return getMapper( mapperTypeElement, sourceModel );
@ -290,7 +291,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
elementUtils.getAllMembers( resultTypeElement )
);
targetAccessors.addAll(
filters.alternativeTargetAccessorMethodsIn(
alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( resultTypeElement )
)
);
@ -405,7 +406,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
elementUtils.getAllMembers( resultTypeElement )
);
targetAccessors.addAll(
filters.alternativeTargetAccessorMethodsIn(
alternativeTargetAccessorMethodsIn(
elementUtils.getAllMembers( resultTypeElement )
)
);
@ -487,16 +488,16 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
private PropertyMapping getPropertyMapping(List<Method> 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<List<Metho
return false;
}
/**
* 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
*/
private List<ExecutableElement> alternativeTargetAccessorMethodsIn(Iterable<? extends Element> elements) {
List<ExecutableElement> setterMethods = filters.setterMethodsIn( elements );
List<ExecutableElement> getterMethods = filters.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.
// 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;
}
}

View File

@ -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<Void, Lis
public List<Method> 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<Void, Lis
}
private Method getMethod(TypeElement element, ExecutableElement method, boolean mapperRequiresImplementation) {
List<Parameter> parameters = executables.retrieveParameters( method );
Type returnType = executables.retrieveReturnType( method );
List<Parameter> 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 );

View File

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

View File

@ -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<? extends VariableElement> 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<Parameter> retrieveParameters(ExecutableElement method) {
List<? extends VariableElement> parameters = method.getParameters();
List<Parameter> result = new ArrayList<Parameter>( 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() );
}
}

View File

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