Extract methods that use the AccessorNamingStrategy into class instance methods

This helps towards #1415, where we need to use strategy based on presence / absence of Immutables
This commit is contained in:
Filip Hrisafov 2018-04-22 09:59:20 +02:00
parent 720854913a
commit 8a24706026
18 changed files with 278 additions and 140 deletions

View File

@ -38,6 +38,7 @@ import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Services;
import org.mapstruct.ap.spi.MappingExclusionProvider;
@ -125,6 +126,7 @@ public class MappingBuilderContext {
private final Elements elementUtils;
private final Types typeUtils;
private final FormattingMessager messager;
private final AccessorNamingUtils accessorNaming;
private final Options options;
private final TypeElement mapperTypeElement;
private final List<SourceMethod> sourceModel;
@ -138,6 +140,7 @@ public class MappingBuilderContext {
Elements elementUtils,
Types typeUtils,
FormattingMessager messager,
AccessorNamingUtils accessorNaming,
Options options,
MappingResolver mappingResolver,
TypeElement mapper,
@ -147,6 +150,7 @@ public class MappingBuilderContext {
this.elementUtils = elementUtils;
this.typeUtils = typeUtils;
this.messager = messager;
this.accessorNaming = accessorNaming;
this.options = options;
this.mappingResolver = mappingResolver;
this.mapperTypeElement = mapper;
@ -195,6 +199,10 @@ public class MappingBuilderContext {
return messager;
}
public AccessorNamingUtils getAccessorNaming() {
return accessorNaming;
}
public Options getOptions() {
return options;
}

View File

@ -50,6 +50,7 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceReference;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message;
@ -86,14 +87,14 @@ public class PropertyMapping extends ModelElement {
SETTER,
ADDER;
public static TargetWriteAccessorType of(Accessor accessor) {
if ( Executables.isSetterMethod( accessor ) ) {
public static TargetWriteAccessorType of(AccessorNamingUtils accessorNaming, Accessor accessor) {
if ( accessorNaming.isSetterMethod( accessor ) ) {
return TargetWriteAccessorType.SETTER;
}
else if ( Executables.isAdderMethod( accessor ) ) {
else if ( accessorNaming.isAdderMethod( accessor ) ) {
return TargetWriteAccessorType.ADDER;
}
else if ( Executables.isGetterMethod( accessor ) ) {
else if ( accessorNaming.isGetterMethod( accessor ) ) {
return TargetWriteAccessorType.GETTER;
}
else {
@ -131,7 +132,7 @@ public class PropertyMapping extends ModelElement {
this.targetReadAccessor = targetProp.getReadAccessor();
this.targetWriteAccessor = targetProp.getWriteAccessor();
this.targetType = targetProp.getType();
this.targetWriteAccessorType = TargetWriteAccessorType.of( targetWriteAccessor );
this.targetWriteAccessorType = TargetWriteAccessorType.of( ctx.getAccessorNaming(), targetWriteAccessor );
return (T) this;
}
@ -142,7 +143,7 @@ public class PropertyMapping extends ModelElement {
public T targetWriteAccessor(Accessor targetWriteAccessor) {
this.targetWriteAccessor = targetWriteAccessor;
this.targetWriteAccessorType = TargetWriteAccessorType.of( targetWriteAccessor );
this.targetWriteAccessorType = TargetWriteAccessorType.of( ctx.getAccessorNaming(), targetWriteAccessor );
this.targetType = determineTargetType();
return (T) this;
@ -785,7 +786,7 @@ public class PropertyMapping extends ModelElement {
if ( assignment != null ) {
if ( Executables.isSetterMethod( targetWriteAccessor ) ||
if ( ctx.getAccessorNaming().isSetterMethod( targetWriteAccessor ) ||
Executables.isFieldAccessor( targetWriteAccessor ) ) {
// target accessor is setter, so decorate assignment as setter
@ -883,7 +884,7 @@ public class PropertyMapping extends ModelElement {
public PropertyMapping build() {
Assignment assignment = new SourceRHS( javaExpression, null, existingVariableNames, "" );
if ( Executables.isSetterMethod( targetWriteAccessor ) ||
if ( ctx.getAccessorNaming().isSetterMethod( targetWriteAccessor ) ||
Executables.isFieldAccessor( targetWriteAccessor ) ) {
// setter, so wrap in setter
assignment = new SetterWrapper( assignment, method.getThrownTypes(), isFieldAssignment() );

View File

@ -44,6 +44,7 @@ import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.Filters;
import org.mapstruct.ap.internal.util.Nouns;
@ -68,6 +69,7 @@ public class Type extends ModelElement implements Comparable<Type> {
private final Types typeUtils;
private final Elements elementUtils;
private final TypeFactory typeFactory;
private final AccessorNamingUtils accessorNaming;
private final TypeMirror typeMirror;
private final TypeElement typeElement;
@ -108,6 +110,7 @@ public class Type extends ModelElement implements Comparable<Type> {
//CHECKSTYLE:OFF
public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming,
TypeMirror typeMirror, TypeElement typeElement,
List<Type> typeParameters, ImplementationType implementationType, Type componentType,
BuilderInfo builderInfo,
@ -119,6 +122,7 @@ public class Type extends ModelElement implements Comparable<Type> {
this.typeUtils = typeUtils;
this.elementUtils = elementUtils;
this.typeFactory = typeFactory;
this.accessorNaming = accessorNaming;
this.typeMirror = typeMirror;
this.typeElement = typeElement;
@ -374,6 +378,7 @@ public class Type extends ModelElement implements Comparable<Type> {
typeUtils,
elementUtils,
typeFactory,
accessorNaming,
typeUtils.erasure( typeMirror ),
typeElement,
typeParameters,
@ -421,26 +426,26 @@ public class Type extends ModelElement implements Comparable<Type> {
*/
public Map<String, Accessor> getPropertyReadAccessors() {
if ( readAccessors == null ) {
List<Accessor> getterList = Filters.getterMethodsIn( getAllAccessors() );
List<Accessor> getterList = Filters.getterMethodsIn( accessorNaming, getAllAccessors() );
Map<String, Accessor> modifiableGetters = new LinkedHashMap<String, Accessor>();
for ( Accessor getter : getterList ) {
String propertyName = Executables.getPropertyName( getter );
String propertyName = accessorNaming.getPropertyName( getter );
if ( modifiableGetters.containsKey( propertyName ) ) {
// In the DefaultAccessorNamingStrategy, this can only be the case for Booleans: isFoo() and
// getFoo(); The latter is preferred.
if ( !getter.getSimpleName().toString().startsWith( "is" ) ) {
modifiableGetters.put( Executables.getPropertyName( getter ), getter );
modifiableGetters.put( accessorNaming.getPropertyName( getter ), getter );
}
}
else {
modifiableGetters.put( Executables.getPropertyName( getter ), getter );
modifiableGetters.put( accessorNaming.getPropertyName( getter ), getter );
}
}
List<Accessor> fieldsList = Filters.fieldsIn( getAllAccessors() );
for ( Accessor field : fieldsList ) {
String propertyName = Executables.getPropertyName( field );
String propertyName = accessorNaming.getPropertyName( field );
if ( !modifiableGetters.containsKey( propertyName ) ) {
// If there was no getter or is method for booleans, then resort to the field.
// If a field was already added do not add it again.
@ -459,11 +464,14 @@ public class Type extends ModelElement implements Comparable<Type> {
*/
public Map<String, ExecutableElementAccessor> getPropertyPresenceCheckers() {
if ( presenceCheckers == null ) {
List<ExecutableElementAccessor> checkerList = Filters.presenceCheckMethodsIn( getAllAccessors() );
List<ExecutableElementAccessor> checkerList = Filters.presenceCheckMethodsIn(
accessorNaming,
getAllAccessors()
);
Map<String, ExecutableElementAccessor> modifiableCheckers = new LinkedHashMap<String,
ExecutableElementAccessor>();
for ( ExecutableElementAccessor checker : checkerList ) {
modifiableCheckers.put( Executables.getPropertyName( checker ), checker );
modifiableCheckers.put( accessorNaming.getPropertyName( checker ), checker );
}
presenceCheckers = Collections.unmodifiableMap( modifiableCheckers );
}
@ -491,7 +499,7 @@ public class Type extends ModelElement implements Comparable<Type> {
Map<String, Accessor> result = new LinkedHashMap<String, Accessor>();
for ( Accessor candidate : candidates ) {
String targetPropertyName = Executables.getPropertyName( candidate );
String targetPropertyName = accessorNaming.getPropertyName( candidate );
Accessor readAccessor = getPropertyReadAccessors().get( targetPropertyName );
@ -507,12 +515,12 @@ public class Type extends ModelElement implements Comparable<Type> {
// first check if there's a setter method.
Accessor adderMethod = null;
if ( Executables.isSetterMethod( candidate )
if ( accessorNaming.isSetterMethod( candidate )
// ok, the current accessor is a setter. So now the strategy determines what to use
&& cmStrategy == CollectionMappingStrategyPrism.ADDER_PREFERRED ) {
adderMethod = getAdderForType( targetType, targetPropertyName );
}
else if ( Executables.isGetterMethod( candidate ) ) {
else if ( accessorNaming.isGetterMethod( candidate ) ) {
// the current accessor is a getter (no setter available). But still, an add method is according
// to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
adderMethod = getAdderForType( targetType, targetPropertyName );
@ -550,7 +558,7 @@ public class Type extends ModelElement implements Comparable<Type> {
if ( parameter != null ) {
return parameter.getType();
}
else if ( Executables.isGetterMethod( candidate ) || Executables.isFieldAccessor( candidate ) ) {
else if ( accessorNaming.isGetterMethod( candidate ) || Executables.isFieldAccessor( candidate ) ) {
return typeFactory.getReturnType( (DeclaredType) typeMirror, candidate );
}
return null;
@ -613,7 +621,7 @@ public class Type extends ModelElement implements Comparable<Type> {
}
else {
for ( Accessor candidate : candidates ) {
String elementName = Executables.getElementNameForAdder( candidate );
String elementName = accessorNaming.getElementNameForAdder( candidate );
if ( elementName != null && elementName.equals( Nouns.singularize( pluralPropertyName ) ) ) {
return candidate;
}
@ -630,7 +638,7 @@ public class Type extends ModelElement implements Comparable<Type> {
*/
private List<Accessor> getSetters() {
if ( setters == null ) {
setters = Collections.unmodifiableList( Filters.setterMethodsIn( getAllAccessors() ) );
setters = Collections.unmodifiableList( Filters.setterMethodsIn( accessorNaming, getAllAccessors() ) );
}
return setters;
}
@ -645,7 +653,7 @@ public class Type extends ModelElement implements Comparable<Type> {
*/
private List<Accessor> getAdders() {
if ( adders == null ) {
adders = Collections.unmodifiableList( Filters.adderMethodsIn( getAllAccessors() ) );
adders = Collections.unmodifiableList( Filters.adderMethodsIn( accessorNaming, getAllAccessors() ) );
}
return adders;
}
@ -691,10 +699,10 @@ public class Type extends ModelElement implements Comparable<Type> {
private boolean correspondingSetterMethodExists(Accessor getterMethod,
List<Accessor> setterMethods) {
String getterPropertyName = Executables.getPropertyName( getterMethod );
String getterPropertyName = accessorNaming.getPropertyName( getterMethod );
for ( Accessor setterMethod : setterMethods ) {
String setterPropertyName = Executables.getPropertyName( setterMethod );
String setterPropertyName = accessorNaming.getPropertyName( setterMethod );
if ( getterPropertyName.equals( setterPropertyName ) ) {
return true;
}

View File

@ -289,6 +289,7 @@ public class TypeFactory {
return new Type(
typeUtils, elementUtils, this,
roundContext.getAnnotationProcessorContext().getAccessorNaming(),
mirror,
typeElement,
getTypeParameters( mirror, false ),
@ -500,6 +501,7 @@ public class TypeFactory {
typeUtils,
elementUtils,
this,
roundContext.getAnnotationProcessorContext().getAccessorNaming(),
typeUtils.getDeclaredType(
implementationType.getTypeElement(),
declaredType.getTypeArguments().toArray( new TypeMirror[] { } )

View File

@ -39,6 +39,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.MappingPrism;
import org.mapstruct.ap.internal.prism.MappingsPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings;
@ -333,8 +334,9 @@ public class Mapping {
( (DeclaredType) mirror ).asElement().getKind() == ElementKind.ENUM;
}
public void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) {
init( method, messager, typeFactory, false, null );
public void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming) {
init( method, messager, typeFactory, accessorNaming, false, null );
}
/**
@ -343,11 +345,13 @@ public class Mapping {
* @param method the source method that the mapping belongs to
* @param messager the messager that can be used for outputting messages
* @param typeFactory the type factory
* @param accessorNaming the accessor naming utils
* @param isReverse whether the init is for a reverse mapping
* @param reverseSourceParameter the source parameter from the revers mapping
*/
private void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory, boolean isReverse,
Parameter reverseSourceParameter) {
private void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming, boolean isReverse,
Parameter reverseSourceParameter) {
if ( !method.isEnumMapping() ) {
sourceReference = new SourceReference.BuilderFromMapping()
@ -363,6 +367,7 @@ public class Mapping {
.method( method )
.messager( messager )
.typeFactory( typeFactory )
.accessorNaming( accessorNaming )
.reverseSourceParameter( reverseSourceParameter )
.build();
}
@ -473,7 +478,8 @@ public class Mapping {
return dependsOn;
}
public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) {
public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming) {
// mapping can only be reversed if the source was not a constant nor an expression nor a nested property
// and the mapping is not a 'target-source-ignore' mapping
@ -502,6 +508,7 @@ public class Mapping {
method,
messager,
typeFactory,
accessorNaming,
true,
sourceReference != null ? sourceReference.getParameter() : null
);

View File

@ -33,6 +33,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.accessor.Accessor;
@ -220,9 +221,11 @@ public class MappingOptions {
* @param method the source method
* @param messager the messager
* @param typeFactory the type factory
* @param accessorNaming the accessor naming utils
*/
public void applyInheritedOptions(MappingOptions inherited, boolean isInverse, SourceMethod method,
FormattingMessager messager, TypeFactory typeFactory) {
FormattingMessager messager, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming) {
if ( null != inherited ) {
if ( getIterableMapping() == null ) {
if ( inherited.getIterableMapping() != null ) {
@ -270,7 +273,7 @@ public class MappingOptions {
for ( List<Mapping> lmappings : inherited.getMappings().values() ) {
for ( Mapping mapping : lmappings ) {
if ( isInverse ) {
mapping = mapping.reverse( method, messager, typeFactory );
mapping = mapping.reverse( method, messager, typeFactory, accessorNaming );
}
if ( mapping != null ) {
@ -297,7 +300,7 @@ public class MappingOptions {
}
public void applyIgnoreAll(MappingOptions inherited, SourceMethod method, FormattingMessager messager,
TypeFactory typeFactory ) {
TypeFactory typeFactory, AccessorNamingUtils accessorNaming) {
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
Type writeType = method.getResultType();
if ( !method.isUpdateMethod() ) {
@ -311,7 +314,7 @@ public class MappingOptions {
for ( String targetPropertyName : writeAccessors.keySet() ) {
if ( !mappedPropertyNames.contains( targetPropertyName ) ) {
Mapping mapping = Mapping.forIgnore( targetPropertyName );
mapping.init( method, messager, typeFactory );
mapping.init( method, messager, typeFactory, accessorNaming );
mappings.put( targetPropertyName, Arrays.asList( mapping ) );
}
}

View File

@ -36,6 +36,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.ObjectFactoryPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.MapperConfiguration;
@ -99,6 +100,7 @@ public class SourceMethod implements Method {
private BeanMapping beanMapping = null;
private Types typeUtils;
private TypeFactory typeFactory = null;
private AccessorNamingUtils accessorNaming = null;
private FormattingMessager messager = null;
private MapperConfiguration mapperConfig = null;
private List<SourceMethod> prototypeMethods = Collections.emptyList();
@ -165,6 +167,11 @@ public class SourceMethod implements Method {
return this;
}
public Builder setAccessorNaming(AccessorNamingUtils accessorNaming) {
this.accessorNaming = accessorNaming;
return this;
}
public Builder setMessager(FormattingMessager messager) {
this.messager = messager;
return this;
@ -200,7 +207,7 @@ public class SourceMethod implements Method {
if ( mappings != null ) {
for ( Map.Entry<String, List<Mapping>> entry : mappings.entrySet() ) {
for ( Mapping mapping : entry.getValue() ) {
mapping.init( sourceMethod, messager, typeFactory );
mapping.init( sourceMethod, messager, typeFactory, accessorNaming );
}
}
}

View File

@ -30,6 +30,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message;
@ -74,6 +75,7 @@ public class TargetReference {
private SourceMethod method;
private FormattingMessager messager;
private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private boolean isReverse;
/**
* Needed when we are building from reverse mapping. It is needed, so we can remove the first level if it is
@ -119,6 +121,11 @@ public class TargetReference {
return this;
}
public BuilderFromTargetMapping accessorNaming(AccessorNamingUtils accessorNaming) {
this.accessorNaming = accessorNaming;
return this;
}
public BuilderFromTargetMapping isReverse(boolean isReverse) {
this.isReverse = isReverse;
return this;
@ -204,7 +211,7 @@ public class TargetReference {
break;
}
if ( isLast || ( Executables.isSetterMethod( targetWriteAccessor )
if ( isLast || ( accessorNaming.isSetterMethod( targetWriteAccessor )
|| Executables.isFieldAccessor( targetWriteAccessor ) ) ) {
// only intermediate nested properties when they are a true setter or field accessor
// the last may be other readAccessor (setter / getter / adder).
@ -234,7 +241,7 @@ public class TargetReference {
private Type findNextType(Type initial, Accessor targetWriteAccessor, Accessor targetReadAccessor) {
Type nextType;
Accessor toUse = targetWriteAccessor != null ? targetWriteAccessor : targetReadAccessor;
if ( Executables.isGetterMethod( toUse ) ||
if ( accessorNaming.isGetterMethod( toUse ) ||
Executables.isFieldAccessor( toUse ) ) {
nextType = typeFactory.getReturnType(
(DeclaredType) typeBasedOnMethod( initial ).getTypeMirror(),

View File

@ -31,6 +31,7 @@ import javax.tools.Diagnostic.Kind;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.RoundContext;
@ -50,12 +51,14 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
private final TypeFactory typeFactory;
private final VersionInformation versionInformation;
private final Types delegatingTypes;
private final AccessorNamingUtils accessorNaming;
public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options,
RoundContext roundContext) {
this.processingEnvironment = processingEnvironment;
this.messager = new DelegatingMessager( processingEnvironment.getMessager() );
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
this.typeFactory = new TypeFactory(
@ -91,6 +94,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
return messager;
}
@Override
public AccessorNamingUtils getAccessorNaming() {
return accessorNaming;
}
@Override
public Options getOptions() {
return options;

View File

@ -62,6 +62,7 @@ import org.mapstruct.ap.internal.prism.MapperPrism;
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.processor.creation.MappingResolverImpl;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message;
@ -85,6 +86,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
private Options options;
private VersionInformation versionInformation;
private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private MappingBuilderContext mappingContext;
@Override
@ -95,6 +97,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
this.options = context.getOptions();
this.versionInformation = context.getVersionInformation();
this.typeFactory = context.getTypeFactory();
this.accessorNaming = context.getAccessorNaming();
MapperConfiguration mapperConfig = MapperConfiguration.getInstanceOn( mapperTypeElement );
List<MapperReference> mapperReferences = initReferencedMappers( mapperTypeElement, mapperConfig );
@ -104,6 +107,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
elementUtils,
typeUtils,
messager,
accessorNaming,
options,
new MappingResolverImpl(
messager,
@ -448,10 +452,24 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// apply defined (@InheritConfiguration, @InheritInverseConfiguration) mappings
if ( forwardMappingOptions != null ) {
mappingOptions.applyInheritedOptions( forwardMappingOptions, false, method, messager, typeFactory );
mappingOptions.applyInheritedOptions(
forwardMappingOptions,
false,
method,
messager,
typeFactory,
accessorNaming
);
}
if ( inverseMappingOptions != null ) {
mappingOptions.applyInheritedOptions( inverseMappingOptions, true, method, messager, typeFactory );
mappingOptions.applyInheritedOptions(
inverseMappingOptions,
true,
method,
messager,
typeFactory,
accessorNaming
);
}
// apply auto inherited options
@ -466,7 +484,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
false,
method,
messager,
typeFactory );
typeFactory,
accessorNaming
);
}
else if ( applicablePrototypeMethods.size() > 1 ) {
messager.printMessage(
@ -484,7 +504,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
true,
method,
messager,
typeFactory );
typeFactory,
accessorNaming
);
}
else if ( applicableReversePrototypeMethods.size() > 1 ) {
messager.printMessage(
@ -497,7 +519,13 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// @BeanMapping( ignoreByDefault = true )
if ( mappingOptions.getBeanMapping() != null && mappingOptions.getBeanMapping().isignoreByDefault() ) {
mappingOptions.applyIgnoreAll( mappingOptions, method, messager, typeFactory );
mappingOptions.applyIgnoreAll(
mappingOptions,
method,
messager,
typeFactory,
accessorNaming
);
}
mappingOptions.markAsFullyInitialized();

View File

@ -55,6 +55,7 @@ import org.mapstruct.ap.internal.prism.MappingsPrism;
import org.mapstruct.ap.internal.prism.ObjectFactoryPrism;
import org.mapstruct.ap.internal.prism.ValueMappingPrism;
import org.mapstruct.ap.internal.prism.ValueMappingsPrism;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager;
@ -73,6 +74,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
private FormattingMessager messager;
private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private Types typeUtils;
private Elements elementUtils;
@ -80,6 +82,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
public List<SourceMethod> process(ProcessorContext context, TypeElement mapperTypeElement, Void sourceModel) {
this.messager = context.getMessager();
this.typeFactory = context.getTypeFactory();
this.accessorNaming = context.getAccessorNaming();
this.typeUtils = context.getTypeUtils();
this.elementUtils = context.getElementUtils();
@ -265,6 +268,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setTypeUtils( typeUtils )
.setMessager( messager )
.setTypeFactory( typeFactory )
.setAccessorNaming( accessorNaming )
.setMapperConfiguration( mapperConfig )
.setPrototypeMethods( prototypeMethods )
.setContextProvidedMethods( contextProvidedMethods )
@ -322,6 +326,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setExceptionTypes( exceptionTypes )
.setTypeUtils( typeUtils )
.setTypeFactory( typeFactory )
.setAccessorNaming( accessorNaming )
.build();
}

View File

@ -26,6 +26,7 @@ import javax.tools.Diagnostic.Kind;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.version.VersionInformation;
@ -61,6 +62,8 @@ public interface ModelElementProcessor<P, R> {
FormattingMessager getMessager();
AccessorNamingUtils getAccessorNaming();
Options getOptions();
VersionInformation getVersionInformation();

View File

@ -0,0 +1,132 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.util;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.SimpleTypeVisitor6;
import org.mapstruct.ap.internal.util.accessor.Accessor;
import org.mapstruct.ap.internal.util.accessor.ExecutableElementAccessor;
import org.mapstruct.ap.spi.AccessorNamingStrategy;
import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy;
import org.mapstruct.ap.spi.MethodType;
import static org.mapstruct.ap.internal.util.Executables.isPublic;
/**
* Utils for working with the {@link AccessorNamingStrategy}.
*
* @author Filip Hrisafov
*/
public final class AccessorNamingUtils {
private final AccessorNamingStrategy accessorNamingStrategy;
public AccessorNamingUtils() {
accessorNamingStrategy = Services.get(
AccessorNamingStrategy.class, new DefaultAccessorNamingStrategy()
);
}
public boolean isGetterMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null && isPublic( method ) &&
executable.getParameters().isEmpty() &&
accessorNamingStrategy.getMethodType( executable ) == MethodType.GETTER;
}
public boolean isPresenceCheckMethod(Accessor method) {
if ( !( method instanceof ExecutableElementAccessor ) ) {
return false;
}
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().isEmpty()
&& ( executable.getReturnType().getKind() == TypeKind.BOOLEAN ||
"java.lang.Boolean".equals( getQualifiedName( executable.getReturnType() ) ) )
&& accessorNamingStrategy.getMethodType( executable ) == MethodType.PRESENCE_CHECKER;
}
public boolean isSetterMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().size() == 1
&& accessorNamingStrategy.getMethodType( executable ) == MethodType.SETTER;
}
public boolean isAdderMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().size() == 1
&& accessorNamingStrategy.getMethodType( executable ) == MethodType.ADDER;
}
public String getPropertyName(Accessor accessor) {
ExecutableElement executable = accessor.getExecutable();
return executable != null ? accessorNamingStrategy.getPropertyName( executable ) :
accessor.getSimpleName().toString();
}
/**
* @param adderMethod the adder method
*
* @return the 'element name' to which an adder method applies. If. e.g. an adder method is named
* {@code addChild(Child v)}, the element name would be 'Child'.
*/
public String getElementNameForAdder(Accessor adderMethod) {
ExecutableElement executable = adderMethod.getExecutable();
return executable != null ? accessorNamingStrategy.getElementName( executable ) : null;
}
private static String getQualifiedName(TypeMirror type) {
DeclaredType declaredType = type.accept(
new SimpleTypeVisitor6<DeclaredType, Void>() {
@Override
public DeclaredType visitDeclared(DeclaredType t, Void p) {
return t;
}
},
null
);
if ( declaredType == null ) {
return null;
}
TypeElement typeElement = declaredType.asElement().accept(
new SimpleElementVisitor6<TypeElement, Void>() {
@Override
public TypeElement visitType(TypeElement e, Void p) {
return e;
}
},
null
);
return typeElement != null ? typeElement.getQualifiedName().toString() : null;
}
}

View File

@ -33,10 +33,12 @@ import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
public class AnnotationProcessorContext {
private List<AstModifyingAnnotationProcessor> astModifyingAnnotationProcessors;
private AccessorNamingUtils accessorNaming;
public AnnotationProcessorContext() {
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
findAstModifyingAnnotationProcessors() );
this.accessorNaming = new AccessorNamingUtils();
}
private static List<AstModifyingAnnotationProcessor> findAstModifyingAnnotationProcessors() {
@ -56,4 +58,8 @@ public class AnnotationProcessorContext {
public List<AstModifyingAnnotationProcessor> getAstModifyingAnnotationProcessors() {
return astModifyingAnnotationProcessors;
}
public AccessorNamingUtils getAccessorNaming() {
return accessorNaming;
}
}

View File

@ -36,17 +36,12 @@ import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.SimpleTypeVisitor6;
import org.mapstruct.ap.internal.prism.AfterMappingPrism;
import org.mapstruct.ap.internal.prism.BeforeMappingPrism;
import org.mapstruct.ap.internal.util.accessor.Accessor;
import org.mapstruct.ap.internal.util.accessor.ExecutableElementAccessor;
import org.mapstruct.ap.internal.util.accessor.VariableElementAccessor;
import org.mapstruct.ap.spi.AccessorNamingStrategy;
import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy;
import org.mapstruct.ap.spi.MethodType;
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
/**
@ -69,20 +64,9 @@ public class Executables {
DEFAULT_METHOD = method;
}
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = Services.get(
AccessorNamingStrategy.class, new DefaultAccessorNamingStrategy()
);
private Executables() {
}
public static boolean isGetterMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null && isPublic( method ) &&
executable.getParameters().isEmpty() &&
ACCESSOR_NAMING_STRATEGY.getMethodType( executable ) == MethodType.GETTER;
}
/**
* An {@link Accessor} is a field accessor, if it doesn't have an executable element, is public and it is not
* static.
@ -96,36 +80,7 @@ public class Executables {
return executable == null && isPublic( accessor ) && isNotStatic( accessor );
}
public static boolean isPresenceCheckMethod(Accessor method) {
if ( !( method instanceof ExecutableElementAccessor ) ) {
return false;
}
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().isEmpty()
&& ( executable.getReturnType().getKind() == TypeKind.BOOLEAN ||
"java.lang.Boolean".equals( getQualifiedName( executable.getReturnType() ) ) )
&& ACCESSOR_NAMING_STRATEGY.getMethodType( executable ) == MethodType.PRESENCE_CHECKER;
}
public static boolean isSetterMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().size() == 1
&& ACCESSOR_NAMING_STRATEGY.getMethodType( executable ) == MethodType.SETTER;
}
public static boolean isAdderMethod(Accessor method) {
ExecutableElement executable = method.getExecutable();
return executable != null
&& isPublic( method )
&& executable.getParameters().size() == 1
&& ACCESSOR_NAMING_STRATEGY.getMethodType( executable ) == MethodType.ADDER;
}
private static boolean isPublic(Accessor method) {
static boolean isPublic(Accessor method) {
return method.getModifiers().contains( Modifier.PUBLIC );
}
@ -137,12 +92,6 @@ public class Executables {
return accessor != null && accessor.getModifiers().contains( Modifier.FINAL );
}
public static String getPropertyName(Accessor accessor) {
ExecutableElement executable = accessor.getExecutable();
return executable != null ? ACCESSOR_NAMING_STRATEGY.getPropertyName( executable ) :
accessor.getSimpleName().toString();
}
public static boolean isDefaultMethod(ExecutableElement method) {
try {
return DEFAULT_METHOD != null && Boolean.TRUE.equals( DEFAULT_METHOD.invoke( method ) );
@ -155,16 +104,6 @@ public class Executables {
}
}
/**
* @param adderMethod the adder method
* @return the 'element name' to which an adder method applies. If. e.g. an adder method is named
* {@code addChild(Child v)}, the element name would be 'Child'.
*/
public static String getElementNameForAdder(Accessor adderMethod) {
ExecutableElement executable = adderMethod.getExecutable();
return executable != null ? ACCESSOR_NAMING_STRATEGY.getElementName( executable ) : null;
}
/**
* @param mirror the type mirror
*
@ -356,33 +295,4 @@ public class Executables {
public static boolean isBeforeMappingMethod(ExecutableElement executableElement) {
return BeforeMappingPrism.getInstanceOn( executableElement ) != null;
}
private static String getQualifiedName(TypeMirror type) {
DeclaredType declaredType = type.accept(
new SimpleTypeVisitor6<DeclaredType, Void>() {
@Override
public DeclaredType visitDeclared(DeclaredType t, Void p) {
return t;
}
},
null
);
if ( declaredType == null ) {
return null;
}
TypeElement typeElement = declaredType.asElement().accept(
new SimpleElementVisitor6<TypeElement, Void>() {
@Override
public TypeElement visitType(TypeElement e, Void p) {
return e;
}
},
null
);
return typeElement != null ? typeElement.getQualifiedName().toString() : null;
}
}

View File

@ -36,11 +36,11 @@ public class Filters {
private Filters() {
}
public static List<Accessor> getterMethodsIn(List<Accessor> elements) {
public static List<Accessor> getterMethodsIn(AccessorNamingUtils accessorNaming, List<Accessor> elements) {
List<Accessor> getterMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) {
if ( Executables.isGetterMethod( method ) ) {
if ( accessorNaming.isGetterMethod( method ) ) {
getterMethods.add( method );
}
}
@ -60,11 +60,12 @@ public class Filters {
return fieldAccessors;
}
public static List<ExecutableElementAccessor> presenceCheckMethodsIn(List<Accessor> elements) {
public static List<ExecutableElementAccessor> presenceCheckMethodsIn(AccessorNamingUtils accessorNaming,
List<Accessor> elements) {
List<ExecutableElementAccessor> presenceCheckMethods = new LinkedList<ExecutableElementAccessor>();
for ( Accessor method : elements ) {
if ( Executables.isPresenceCheckMethod( method ) ) {
if ( accessorNaming.isPresenceCheckMethod( method ) ) {
presenceCheckMethods.add( (ExecutableElementAccessor) method );
}
}
@ -72,22 +73,22 @@ public class Filters {
return presenceCheckMethods;
}
public static List<Accessor> setterMethodsIn(List<Accessor> elements) {
public static List<Accessor> setterMethodsIn(AccessorNamingUtils accessorNaming, List<Accessor> elements) {
List<Accessor> setterMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) {
if ( Executables.isSetterMethod( method ) ) {
if ( accessorNaming.isSetterMethod( method ) ) {
setterMethods.add( method );
}
}
return setterMethods;
}
public static List<Accessor> adderMethodsIn(List<Accessor> elements) {
public static List<Accessor> adderMethodsIn(AccessorNamingUtils accessorNaming, List<Accessor> elements) {
List<Accessor> adderMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) {
if ( Executables.isAdderMethod( method ) ) {
if ( accessorNaming.isAdderMethod( method ) ) {
adderMethods.add( method );
}
}

View File

@ -168,6 +168,7 @@ public class DateFormatValidatorFactoryTest {
null,
null,
null,
null,
voidTypeMirror,
null,
null,

View File

@ -119,6 +119,7 @@ public class DefaultConversionContextTest {
null,
null,
null,
null,
voidTypeMirror,
null,
null,