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.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceMethod; import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.option.Options; 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.FormattingMessager;
import org.mapstruct.ap.internal.util.Services; import org.mapstruct.ap.internal.util.Services;
import org.mapstruct.ap.spi.MappingExclusionProvider; import org.mapstruct.ap.spi.MappingExclusionProvider;
@ -125,6 +126,7 @@ public class MappingBuilderContext {
private final Elements elementUtils; private final Elements elementUtils;
private final Types typeUtils; private final Types typeUtils;
private final FormattingMessager messager; private final FormattingMessager messager;
private final AccessorNamingUtils accessorNaming;
private final Options options; private final Options options;
private final TypeElement mapperTypeElement; private final TypeElement mapperTypeElement;
private final List<SourceMethod> sourceModel; private final List<SourceMethod> sourceModel;
@ -138,6 +140,7 @@ public class MappingBuilderContext {
Elements elementUtils, Elements elementUtils,
Types typeUtils, Types typeUtils,
FormattingMessager messager, FormattingMessager messager,
AccessorNamingUtils accessorNaming,
Options options, Options options,
MappingResolver mappingResolver, MappingResolver mappingResolver,
TypeElement mapper, TypeElement mapper,
@ -147,6 +150,7 @@ public class MappingBuilderContext {
this.elementUtils = elementUtils; this.elementUtils = elementUtils;
this.typeUtils = typeUtils; this.typeUtils = typeUtils;
this.messager = messager; this.messager = messager;
this.accessorNaming = accessorNaming;
this.options = options; this.options = options;
this.mappingResolver = mappingResolver; this.mappingResolver = mappingResolver;
this.mapperTypeElement = mapper; this.mapperTypeElement = mapper;
@ -195,6 +199,10 @@ public class MappingBuilderContext {
return messager; return messager;
} }
public AccessorNamingUtils getAccessorNaming() {
return accessorNaming;
}
public Options getOptions() { public Options getOptions() {
return options; 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.model.source.SourceReference;
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; 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.Executables;
import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
@ -86,14 +87,14 @@ public class PropertyMapping extends ModelElement {
SETTER, SETTER,
ADDER; ADDER;
public static TargetWriteAccessorType of(Accessor accessor) { public static TargetWriteAccessorType of(AccessorNamingUtils accessorNaming, Accessor accessor) {
if ( Executables.isSetterMethod( accessor ) ) { if ( accessorNaming.isSetterMethod( accessor ) ) {
return TargetWriteAccessorType.SETTER; return TargetWriteAccessorType.SETTER;
} }
else if ( Executables.isAdderMethod( accessor ) ) { else if ( accessorNaming.isAdderMethod( accessor ) ) {
return TargetWriteAccessorType.ADDER; return TargetWriteAccessorType.ADDER;
} }
else if ( Executables.isGetterMethod( accessor ) ) { else if ( accessorNaming.isGetterMethod( accessor ) ) {
return TargetWriteAccessorType.GETTER; return TargetWriteAccessorType.GETTER;
} }
else { else {
@ -131,7 +132,7 @@ public class PropertyMapping extends ModelElement {
this.targetReadAccessor = targetProp.getReadAccessor(); this.targetReadAccessor = targetProp.getReadAccessor();
this.targetWriteAccessor = targetProp.getWriteAccessor(); this.targetWriteAccessor = targetProp.getWriteAccessor();
this.targetType = targetProp.getType(); this.targetType = targetProp.getType();
this.targetWriteAccessorType = TargetWriteAccessorType.of( targetWriteAccessor ); this.targetWriteAccessorType = TargetWriteAccessorType.of( ctx.getAccessorNaming(), targetWriteAccessor );
return (T) this; return (T) this;
} }
@ -142,7 +143,7 @@ public class PropertyMapping extends ModelElement {
public T targetWriteAccessor(Accessor targetWriteAccessor) { public T targetWriteAccessor(Accessor targetWriteAccessor) {
this.targetWriteAccessor = targetWriteAccessor; this.targetWriteAccessor = targetWriteAccessor;
this.targetWriteAccessorType = TargetWriteAccessorType.of( targetWriteAccessor ); this.targetWriteAccessorType = TargetWriteAccessorType.of( ctx.getAccessorNaming(), targetWriteAccessor );
this.targetType = determineTargetType(); this.targetType = determineTargetType();
return (T) this; return (T) this;
@ -785,7 +786,7 @@ public class PropertyMapping extends ModelElement {
if ( assignment != null ) { if ( assignment != null ) {
if ( Executables.isSetterMethod( targetWriteAccessor ) || if ( ctx.getAccessorNaming().isSetterMethod( targetWriteAccessor ) ||
Executables.isFieldAccessor( targetWriteAccessor ) ) { Executables.isFieldAccessor( targetWriteAccessor ) ) {
// target accessor is setter, so decorate assignment as setter // target accessor is setter, so decorate assignment as setter
@ -883,7 +884,7 @@ public class PropertyMapping extends ModelElement {
public PropertyMapping build() { public PropertyMapping build() {
Assignment assignment = new SourceRHS( javaExpression, null, existingVariableNames, "" ); Assignment assignment = new SourceRHS( javaExpression, null, existingVariableNames, "" );
if ( Executables.isSetterMethod( targetWriteAccessor ) || if ( ctx.getAccessorNaming().isSetterMethod( targetWriteAccessor ) ||
Executables.isFieldAccessor( targetWriteAccessor ) ) { Executables.isFieldAccessor( targetWriteAccessor ) ) {
// setter, so wrap in setter // setter, so wrap in setter
assignment = new SetterWrapper( assignment, method.getThrownTypes(), isFieldAssignment() ); 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 javax.lang.model.util.Types;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism; 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.Executables;
import org.mapstruct.ap.internal.util.Filters; import org.mapstruct.ap.internal.util.Filters;
import org.mapstruct.ap.internal.util.Nouns; 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 Types typeUtils;
private final Elements elementUtils; private final Elements elementUtils;
private final TypeFactory typeFactory; private final TypeFactory typeFactory;
private final AccessorNamingUtils accessorNaming;
private final TypeMirror typeMirror; private final TypeMirror typeMirror;
private final TypeElement typeElement; private final TypeElement typeElement;
@ -108,6 +110,7 @@ public class Type extends ModelElement implements Comparable<Type> {
//CHECKSTYLE:OFF //CHECKSTYLE:OFF
public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory, public Type(Types typeUtils, Elements elementUtils, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming,
TypeMirror typeMirror, TypeElement typeElement, TypeMirror typeMirror, TypeElement typeElement,
List<Type> typeParameters, ImplementationType implementationType, Type componentType, List<Type> typeParameters, ImplementationType implementationType, Type componentType,
BuilderInfo builderInfo, BuilderInfo builderInfo,
@ -119,6 +122,7 @@ public class Type extends ModelElement implements Comparable<Type> {
this.typeUtils = typeUtils; this.typeUtils = typeUtils;
this.elementUtils = elementUtils; this.elementUtils = elementUtils;
this.typeFactory = typeFactory; this.typeFactory = typeFactory;
this.accessorNaming = accessorNaming;
this.typeMirror = typeMirror; this.typeMirror = typeMirror;
this.typeElement = typeElement; this.typeElement = typeElement;
@ -374,6 +378,7 @@ public class Type extends ModelElement implements Comparable<Type> {
typeUtils, typeUtils,
elementUtils, elementUtils,
typeFactory, typeFactory,
accessorNaming,
typeUtils.erasure( typeMirror ), typeUtils.erasure( typeMirror ),
typeElement, typeElement,
typeParameters, typeParameters,
@ -421,26 +426,26 @@ public class Type extends ModelElement implements Comparable<Type> {
*/ */
public Map<String, Accessor> getPropertyReadAccessors() { public Map<String, Accessor> getPropertyReadAccessors() {
if ( readAccessors == null ) { if ( readAccessors == null ) {
List<Accessor> getterList = Filters.getterMethodsIn( getAllAccessors() ); List<Accessor> getterList = Filters.getterMethodsIn( accessorNaming, getAllAccessors() );
Map<String, Accessor> modifiableGetters = new LinkedHashMap<String, Accessor>(); Map<String, Accessor> modifiableGetters = new LinkedHashMap<String, Accessor>();
for ( Accessor getter : getterList ) { for ( Accessor getter : getterList ) {
String propertyName = Executables.getPropertyName( getter ); String propertyName = accessorNaming.getPropertyName( getter );
if ( modifiableGetters.containsKey( propertyName ) ) { if ( modifiableGetters.containsKey( propertyName ) ) {
// In the DefaultAccessorNamingStrategy, this can only be the case for Booleans: isFoo() and // In the DefaultAccessorNamingStrategy, this can only be the case for Booleans: isFoo() and
// getFoo(); The latter is preferred. // getFoo(); The latter is preferred.
if ( !getter.getSimpleName().toString().startsWith( "is" ) ) { if ( !getter.getSimpleName().toString().startsWith( "is" ) ) {
modifiableGetters.put( Executables.getPropertyName( getter ), getter ); modifiableGetters.put( accessorNaming.getPropertyName( getter ), getter );
} }
} }
else { else {
modifiableGetters.put( Executables.getPropertyName( getter ), getter ); modifiableGetters.put( accessorNaming.getPropertyName( getter ), getter );
} }
} }
List<Accessor> fieldsList = Filters.fieldsIn( getAllAccessors() ); List<Accessor> fieldsList = Filters.fieldsIn( getAllAccessors() );
for ( Accessor field : fieldsList ) { for ( Accessor field : fieldsList ) {
String propertyName = Executables.getPropertyName( field ); String propertyName = accessorNaming.getPropertyName( field );
if ( !modifiableGetters.containsKey( propertyName ) ) { if ( !modifiableGetters.containsKey( propertyName ) ) {
// If there was no getter or is method for booleans, then resort to the field. // 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. // 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() { public Map<String, ExecutableElementAccessor> getPropertyPresenceCheckers() {
if ( presenceCheckers == null ) { if ( presenceCheckers == null ) {
List<ExecutableElementAccessor> checkerList = Filters.presenceCheckMethodsIn( getAllAccessors() ); List<ExecutableElementAccessor> checkerList = Filters.presenceCheckMethodsIn(
accessorNaming,
getAllAccessors()
);
Map<String, ExecutableElementAccessor> modifiableCheckers = new LinkedHashMap<String, Map<String, ExecutableElementAccessor> modifiableCheckers = new LinkedHashMap<String,
ExecutableElementAccessor>(); ExecutableElementAccessor>();
for ( ExecutableElementAccessor checker : checkerList ) { for ( ExecutableElementAccessor checker : checkerList ) {
modifiableCheckers.put( Executables.getPropertyName( checker ), checker ); modifiableCheckers.put( accessorNaming.getPropertyName( checker ), checker );
} }
presenceCheckers = Collections.unmodifiableMap( modifiableCheckers ); presenceCheckers = Collections.unmodifiableMap( modifiableCheckers );
} }
@ -491,7 +499,7 @@ public class Type extends ModelElement implements Comparable<Type> {
Map<String, Accessor> result = new LinkedHashMap<String, Accessor>(); Map<String, Accessor> result = new LinkedHashMap<String, Accessor>();
for ( Accessor candidate : candidates ) { for ( Accessor candidate : candidates ) {
String targetPropertyName = Executables.getPropertyName( candidate ); String targetPropertyName = accessorNaming.getPropertyName( candidate );
Accessor readAccessor = getPropertyReadAccessors().get( targetPropertyName ); 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. // first check if there's a setter method.
Accessor adderMethod = null; 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 // ok, the current accessor is a setter. So now the strategy determines what to use
&& cmStrategy == CollectionMappingStrategyPrism.ADDER_PREFERRED ) { && cmStrategy == CollectionMappingStrategyPrism.ADDER_PREFERRED ) {
adderMethod = getAdderForType( targetType, targetPropertyName ); 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 // 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. // to the above strategy (SETTER_PREFERRED || ADDER_PREFERRED) preferred over the getter.
adderMethod = getAdderForType( targetType, targetPropertyName ); adderMethod = getAdderForType( targetType, targetPropertyName );
@ -550,7 +558,7 @@ public class Type extends ModelElement implements Comparable<Type> {
if ( parameter != null ) { if ( parameter != null ) {
return parameter.getType(); 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 typeFactory.getReturnType( (DeclaredType) typeMirror, candidate );
} }
return null; return null;
@ -613,7 +621,7 @@ public class Type extends ModelElement implements Comparable<Type> {
} }
else { else {
for ( Accessor candidate : candidates ) { for ( Accessor candidate : candidates ) {
String elementName = Executables.getElementNameForAdder( candidate ); String elementName = accessorNaming.getElementNameForAdder( candidate );
if ( elementName != null && elementName.equals( Nouns.singularize( pluralPropertyName ) ) ) { if ( elementName != null && elementName.equals( Nouns.singularize( pluralPropertyName ) ) ) {
return candidate; return candidate;
} }
@ -630,7 +638,7 @@ public class Type extends ModelElement implements Comparable<Type> {
*/ */
private List<Accessor> getSetters() { private List<Accessor> getSetters() {
if ( setters == null ) { if ( setters == null ) {
setters = Collections.unmodifiableList( Filters.setterMethodsIn( getAllAccessors() ) ); setters = Collections.unmodifiableList( Filters.setterMethodsIn( accessorNaming, getAllAccessors() ) );
} }
return setters; return setters;
} }
@ -645,7 +653,7 @@ public class Type extends ModelElement implements Comparable<Type> {
*/ */
private List<Accessor> getAdders() { private List<Accessor> getAdders() {
if ( adders == null ) { if ( adders == null ) {
adders = Collections.unmodifiableList( Filters.adderMethodsIn( getAllAccessors() ) ); adders = Collections.unmodifiableList( Filters.adderMethodsIn( accessorNaming, getAllAccessors() ) );
} }
return adders; return adders;
} }
@ -691,10 +699,10 @@ public class Type extends ModelElement implements Comparable<Type> {
private boolean correspondingSetterMethodExists(Accessor getterMethod, private boolean correspondingSetterMethodExists(Accessor getterMethod,
List<Accessor> setterMethods) { List<Accessor> setterMethods) {
String getterPropertyName = Executables.getPropertyName( getterMethod ); String getterPropertyName = accessorNaming.getPropertyName( getterMethod );
for ( Accessor setterMethod : setterMethods ) { for ( Accessor setterMethod : setterMethods ) {
String setterPropertyName = Executables.getPropertyName( setterMethod ); String setterPropertyName = accessorNaming.getPropertyName( setterMethod );
if ( getterPropertyName.equals( setterPropertyName ) ) { if ( getterPropertyName.equals( setterPropertyName ) ) {
return true; return true;
} }

View File

@ -289,6 +289,7 @@ public class TypeFactory {
return new Type( return new Type(
typeUtils, elementUtils, this, typeUtils, elementUtils, this,
roundContext.getAnnotationProcessorContext().getAccessorNaming(),
mirror, mirror,
typeElement, typeElement,
getTypeParameters( mirror, false ), getTypeParameters( mirror, false ),
@ -500,6 +501,7 @@ public class TypeFactory {
typeUtils, typeUtils,
elementUtils, elementUtils,
this, this,
roundContext.getAnnotationProcessorContext().getAccessorNaming(),
typeUtils.getDeclaredType( typeUtils.getDeclaredType(
implementationType.getTypeElement(), implementationType.getTypeElement(),
declaredType.getTypeArguments().toArray( new TypeMirror[] { } ) 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.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.MappingPrism; import org.mapstruct.ap.internal.prism.MappingPrism;
import org.mapstruct.ap.internal.prism.MappingsPrism; 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.FormattingMessager;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings; import org.mapstruct.ap.internal.util.Strings;
@ -333,8 +334,9 @@ public class Mapping {
( (DeclaredType) mirror ).asElement().getKind() == ElementKind.ENUM; ( (DeclaredType) mirror ).asElement().getKind() == ElementKind.ENUM;
} }
public void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) { public void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory,
init( method, messager, typeFactory, false, null ); 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 method the source method that the mapping belongs to
* @param messager the messager that can be used for outputting messages * @param messager the messager that can be used for outputting messages
* @param typeFactory the type factory * @param typeFactory the type factory
* @param accessorNaming the accessor naming utils
* @param isReverse whether the init is for a reverse mapping * @param isReverse whether the init is for a reverse mapping
* @param reverseSourceParameter the source parameter from the revers mapping * @param reverseSourceParameter the source parameter from the revers mapping
*/ */
private void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory, boolean isReverse, private void init(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory,
Parameter reverseSourceParameter) { AccessorNamingUtils accessorNaming, boolean isReverse,
Parameter reverseSourceParameter) {
if ( !method.isEnumMapping() ) { if ( !method.isEnumMapping() ) {
sourceReference = new SourceReference.BuilderFromMapping() sourceReference = new SourceReference.BuilderFromMapping()
@ -363,6 +367,7 @@ public class Mapping {
.method( method ) .method( method )
.messager( messager ) .messager( messager )
.typeFactory( typeFactory ) .typeFactory( typeFactory )
.accessorNaming( accessorNaming )
.reverseSourceParameter( reverseSourceParameter ) .reverseSourceParameter( reverseSourceParameter )
.build(); .build();
} }
@ -473,7 +478,8 @@ public class Mapping {
return dependsOn; 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 // 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 // and the mapping is not a 'target-source-ignore' mapping
@ -502,6 +508,7 @@ public class Mapping {
method, method,
messager, messager,
typeFactory, typeFactory,
accessorNaming,
true, true,
sourceReference != null ? sourceReference.getParameter() : null 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.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism; 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.FormattingMessager;
import org.mapstruct.ap.internal.util.accessor.Accessor; import org.mapstruct.ap.internal.util.accessor.Accessor;
@ -220,9 +221,11 @@ public class MappingOptions {
* @param method the source method * @param method the source method
* @param messager the messager * @param messager the messager
* @param typeFactory the type factory * @param typeFactory the type factory
* @param accessorNaming the accessor naming utils
*/ */
public void applyInheritedOptions(MappingOptions inherited, boolean isInverse, SourceMethod method, public void applyInheritedOptions(MappingOptions inherited, boolean isInverse, SourceMethod method,
FormattingMessager messager, TypeFactory typeFactory) { FormattingMessager messager, TypeFactory typeFactory,
AccessorNamingUtils accessorNaming) {
if ( null != inherited ) { if ( null != inherited ) {
if ( getIterableMapping() == null ) { if ( getIterableMapping() == null ) {
if ( inherited.getIterableMapping() != null ) { if ( inherited.getIterableMapping() != null ) {
@ -270,7 +273,7 @@ public class MappingOptions {
for ( List<Mapping> lmappings : inherited.getMappings().values() ) { for ( List<Mapping> lmappings : inherited.getMappings().values() ) {
for ( Mapping mapping : lmappings ) { for ( Mapping mapping : lmappings ) {
if ( isInverse ) { if ( isInverse ) {
mapping = mapping.reverse( method, messager, typeFactory ); mapping = mapping.reverse( method, messager, typeFactory, accessorNaming );
} }
if ( mapping != null ) { if ( mapping != null ) {
@ -297,7 +300,7 @@ public class MappingOptions {
} }
public void applyIgnoreAll(MappingOptions inherited, SourceMethod method, FormattingMessager messager, public void applyIgnoreAll(MappingOptions inherited, SourceMethod method, FormattingMessager messager,
TypeFactory typeFactory ) { TypeFactory typeFactory, AccessorNamingUtils accessorNaming) {
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy(); CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
Type writeType = method.getResultType(); Type writeType = method.getResultType();
if ( !method.isUpdateMethod() ) { if ( !method.isUpdateMethod() ) {
@ -311,7 +314,7 @@ public class MappingOptions {
for ( String targetPropertyName : writeAccessors.keySet() ) { for ( String targetPropertyName : writeAccessors.keySet() ) {
if ( !mappedPropertyNames.contains( targetPropertyName ) ) { if ( !mappedPropertyNames.contains( targetPropertyName ) ) {
Mapping mapping = Mapping.forIgnore( targetPropertyName ); Mapping mapping = Mapping.forIgnore( targetPropertyName );
mapping.init( method, messager, typeFactory ); mapping.init( method, messager, typeFactory, accessorNaming );
mappings.put( targetPropertyName, Arrays.asList( mapping ) ); 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.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.ObjectFactoryPrism; 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.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.MapperConfiguration;
@ -99,6 +100,7 @@ public class SourceMethod implements Method {
private BeanMapping beanMapping = null; private BeanMapping beanMapping = null;
private Types typeUtils; private Types typeUtils;
private TypeFactory typeFactory = null; private TypeFactory typeFactory = null;
private AccessorNamingUtils accessorNaming = null;
private FormattingMessager messager = null; private FormattingMessager messager = null;
private MapperConfiguration mapperConfig = null; private MapperConfiguration mapperConfig = null;
private List<SourceMethod> prototypeMethods = Collections.emptyList(); private List<SourceMethod> prototypeMethods = Collections.emptyList();
@ -165,6 +167,11 @@ public class SourceMethod implements Method {
return this; return this;
} }
public Builder setAccessorNaming(AccessorNamingUtils accessorNaming) {
this.accessorNaming = accessorNaming;
return this;
}
public Builder setMessager(FormattingMessager messager) { public Builder setMessager(FormattingMessager messager) {
this.messager = messager; this.messager = messager;
return this; return this;
@ -200,7 +207,7 @@ public class SourceMethod implements Method {
if ( mappings != null ) { if ( mappings != null ) {
for ( Map.Entry<String, List<Mapping>> entry : mappings.entrySet() ) { for ( Map.Entry<String, List<Mapping>> entry : mappings.entrySet() ) {
for ( Mapping mapping : entry.getValue() ) { 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.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism; 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.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
@ -74,6 +75,7 @@ public class TargetReference {
private SourceMethod method; private SourceMethod method;
private FormattingMessager messager; private FormattingMessager messager;
private TypeFactory typeFactory; private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private boolean isReverse; private boolean isReverse;
/** /**
* Needed when we are building from reverse mapping. It is needed, so we can remove the first level if it is * 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; return this;
} }
public BuilderFromTargetMapping accessorNaming(AccessorNamingUtils accessorNaming) {
this.accessorNaming = accessorNaming;
return this;
}
public BuilderFromTargetMapping isReverse(boolean isReverse) { public BuilderFromTargetMapping isReverse(boolean isReverse) {
this.isReverse = isReverse; this.isReverse = isReverse;
return this; return this;
@ -204,7 +211,7 @@ public class TargetReference {
break; break;
} }
if ( isLast || ( Executables.isSetterMethod( targetWriteAccessor ) if ( isLast || ( accessorNaming.isSetterMethod( targetWriteAccessor )
|| Executables.isFieldAccessor( targetWriteAccessor ) ) ) { || Executables.isFieldAccessor( targetWriteAccessor ) ) ) {
// only intermediate nested properties when they are a true setter or field accessor // only intermediate nested properties when they are a true setter or field accessor
// the last may be other readAccessor (setter / getter / adder). // 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) { private Type findNextType(Type initial, Accessor targetWriteAccessor, Accessor targetReadAccessor) {
Type nextType; Type nextType;
Accessor toUse = targetWriteAccessor != null ? targetWriteAccessor : targetReadAccessor; Accessor toUse = targetWriteAccessor != null ? targetWriteAccessor : targetReadAccessor;
if ( Executables.isGetterMethod( toUse ) || if ( accessorNaming.isGetterMethod( toUse ) ||
Executables.isFieldAccessor( toUse ) ) { Executables.isFieldAccessor( toUse ) ) {
nextType = typeFactory.getReturnType( nextType = typeFactory.getReturnType(
(DeclaredType) typeBasedOnMethod( initial ).getTypeMirror(), (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.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.Options; import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext; 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.FormattingMessager;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.RoundContext; import org.mapstruct.ap.internal.util.RoundContext;
@ -50,12 +51,14 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
private final TypeFactory typeFactory; private final TypeFactory typeFactory;
private final VersionInformation versionInformation; private final VersionInformation versionInformation;
private final Types delegatingTypes; private final Types delegatingTypes;
private final AccessorNamingUtils accessorNaming;
public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options, public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options,
RoundContext roundContext) { RoundContext roundContext) {
this.processingEnvironment = processingEnvironment; this.processingEnvironment = processingEnvironment;
this.messager = new DelegatingMessager( processingEnvironment.getMessager() ); this.messager = new DelegatingMessager( processingEnvironment.getMessager() );
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment ); this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation ); this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
this.typeFactory = new TypeFactory( this.typeFactory = new TypeFactory(
@ -91,6 +94,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
return messager; return messager;
} }
@Override
public AccessorNamingUtils getAccessorNaming() {
return accessorNaming;
}
@Override @Override
public Options getOptions() { public Options getOptions() {
return options; 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.MappingInheritanceStrategyPrism;
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism; import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
import org.mapstruct.ap.internal.processor.creation.MappingResolverImpl; 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.FormattingMessager;
import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Message; import org.mapstruct.ap.internal.util.Message;
@ -85,6 +86,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
private Options options; private Options options;
private VersionInformation versionInformation; private VersionInformation versionInformation;
private TypeFactory typeFactory; private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private MappingBuilderContext mappingContext; private MappingBuilderContext mappingContext;
@Override @Override
@ -95,6 +97,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
this.options = context.getOptions(); this.options = context.getOptions();
this.versionInformation = context.getVersionInformation(); this.versionInformation = context.getVersionInformation();
this.typeFactory = context.getTypeFactory(); this.typeFactory = context.getTypeFactory();
this.accessorNaming = context.getAccessorNaming();
MapperConfiguration mapperConfig = MapperConfiguration.getInstanceOn( mapperTypeElement ); MapperConfiguration mapperConfig = MapperConfiguration.getInstanceOn( mapperTypeElement );
List<MapperReference> mapperReferences = initReferencedMappers( mapperTypeElement, mapperConfig ); List<MapperReference> mapperReferences = initReferencedMappers( mapperTypeElement, mapperConfig );
@ -104,6 +107,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
elementUtils, elementUtils,
typeUtils, typeUtils,
messager, messager,
accessorNaming,
options, options,
new MappingResolverImpl( new MappingResolverImpl(
messager, messager,
@ -448,10 +452,24 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// apply defined (@InheritConfiguration, @InheritInverseConfiguration) mappings // apply defined (@InheritConfiguration, @InheritInverseConfiguration) mappings
if ( forwardMappingOptions != null ) { if ( forwardMappingOptions != null ) {
mappingOptions.applyInheritedOptions( forwardMappingOptions, false, method, messager, typeFactory ); mappingOptions.applyInheritedOptions(
forwardMappingOptions,
false,
method,
messager,
typeFactory,
accessorNaming
);
} }
if ( inverseMappingOptions != null ) { if ( inverseMappingOptions != null ) {
mappingOptions.applyInheritedOptions( inverseMappingOptions, true, method, messager, typeFactory ); mappingOptions.applyInheritedOptions(
inverseMappingOptions,
true,
method,
messager,
typeFactory,
accessorNaming
);
} }
// apply auto inherited options // apply auto inherited options
@ -466,7 +484,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
false, false,
method, method,
messager, messager,
typeFactory ); typeFactory,
accessorNaming
);
} }
else if ( applicablePrototypeMethods.size() > 1 ) { else if ( applicablePrototypeMethods.size() > 1 ) {
messager.printMessage( messager.printMessage(
@ -484,7 +504,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
true, true,
method, method,
messager, messager,
typeFactory ); typeFactory,
accessorNaming
);
} }
else if ( applicableReversePrototypeMethods.size() > 1 ) { else if ( applicableReversePrototypeMethods.size() > 1 ) {
messager.printMessage( messager.printMessage(
@ -497,7 +519,13 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// @BeanMapping( ignoreByDefault = true ) // @BeanMapping( ignoreByDefault = true )
if ( mappingOptions.getBeanMapping() != null && mappingOptions.getBeanMapping().isignoreByDefault() ) { if ( mappingOptions.getBeanMapping() != null && mappingOptions.getBeanMapping().isignoreByDefault() ) {
mappingOptions.applyIgnoreAll( mappingOptions, method, messager, typeFactory ); mappingOptions.applyIgnoreAll(
mappingOptions,
method,
messager,
typeFactory,
accessorNaming
);
} }
mappingOptions.markAsFullyInitialized(); 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.ObjectFactoryPrism;
import org.mapstruct.ap.internal.prism.ValueMappingPrism; import org.mapstruct.ap.internal.prism.ValueMappingPrism;
import org.mapstruct.ap.internal.prism.ValueMappingsPrism; 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.AnnotationProcessingException;
import org.mapstruct.ap.internal.util.Executables; import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
@ -73,6 +74,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
private FormattingMessager messager; private FormattingMessager messager;
private TypeFactory typeFactory; private TypeFactory typeFactory;
private AccessorNamingUtils accessorNaming;
private Types typeUtils; private Types typeUtils;
private Elements elementUtils; private Elements elementUtils;
@ -80,6 +82,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
public List<SourceMethod> process(ProcessorContext context, TypeElement mapperTypeElement, Void sourceModel) { public List<SourceMethod> process(ProcessorContext context, TypeElement mapperTypeElement, Void sourceModel) {
this.messager = context.getMessager(); this.messager = context.getMessager();
this.typeFactory = context.getTypeFactory(); this.typeFactory = context.getTypeFactory();
this.accessorNaming = context.getAccessorNaming();
this.typeUtils = context.getTypeUtils(); this.typeUtils = context.getTypeUtils();
this.elementUtils = context.getElementUtils(); this.elementUtils = context.getElementUtils();
@ -265,6 +268,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setTypeUtils( typeUtils ) .setTypeUtils( typeUtils )
.setMessager( messager ) .setMessager( messager )
.setTypeFactory( typeFactory ) .setTypeFactory( typeFactory )
.setAccessorNaming( accessorNaming )
.setMapperConfiguration( mapperConfig ) .setMapperConfiguration( mapperConfig )
.setPrototypeMethods( prototypeMethods ) .setPrototypeMethods( prototypeMethods )
.setContextProvidedMethods( contextProvidedMethods ) .setContextProvidedMethods( contextProvidedMethods )
@ -322,6 +326,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setExceptionTypes( exceptionTypes ) .setExceptionTypes( exceptionTypes )
.setTypeUtils( typeUtils ) .setTypeUtils( typeUtils )
.setTypeFactory( typeFactory ) .setTypeFactory( typeFactory )
.setAccessorNaming( accessorNaming )
.build(); .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.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.Options; 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.FormattingMessager;
import org.mapstruct.ap.internal.version.VersionInformation; import org.mapstruct.ap.internal.version.VersionInformation;
@ -61,6 +62,8 @@ public interface ModelElementProcessor<P, R> {
FormattingMessager getMessager(); FormattingMessager getMessager();
AccessorNamingUtils getAccessorNaming();
Options getOptions(); Options getOptions();
VersionInformation getVersionInformation(); 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 { public class AnnotationProcessorContext {
private List<AstModifyingAnnotationProcessor> astModifyingAnnotationProcessors; private List<AstModifyingAnnotationProcessor> astModifyingAnnotationProcessors;
private AccessorNamingUtils accessorNaming;
public AnnotationProcessorContext() { public AnnotationProcessorContext() {
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList( astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
findAstModifyingAnnotationProcessors() ); findAstModifyingAnnotationProcessors() );
this.accessorNaming = new AccessorNamingUtils();
} }
private static List<AstModifyingAnnotationProcessor> findAstModifyingAnnotationProcessors() { private static List<AstModifyingAnnotationProcessor> findAstModifyingAnnotationProcessors() {
@ -56,4 +58,8 @@ public class AnnotationProcessorContext {
public List<AstModifyingAnnotationProcessor> getAstModifyingAnnotationProcessors() { public List<AstModifyingAnnotationProcessor> getAstModifyingAnnotationProcessors() {
return astModifyingAnnotationProcessors; 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.TypeKind;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements; 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.AfterMappingPrism;
import org.mapstruct.ap.internal.prism.BeforeMappingPrism; import org.mapstruct.ap.internal.prism.BeforeMappingPrism;
import org.mapstruct.ap.internal.util.accessor.Accessor; import org.mapstruct.ap.internal.util.accessor.Accessor;
import org.mapstruct.ap.internal.util.accessor.ExecutableElementAccessor; import org.mapstruct.ap.internal.util.accessor.ExecutableElementAccessor;
import org.mapstruct.ap.internal.util.accessor.VariableElementAccessor; 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; import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
/** /**
@ -69,20 +64,9 @@ public class Executables {
DEFAULT_METHOD = method; DEFAULT_METHOD = method;
} }
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = Services.get(
AccessorNamingStrategy.class, new DefaultAccessorNamingStrategy()
);
private Executables() { 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 * An {@link Accessor} is a field accessor, if it doesn't have an executable element, is public and it is not
* static. * static.
@ -96,36 +80,7 @@ public class Executables {
return executable == null && isPublic( accessor ) && isNotStatic( accessor ); return executable == null && isPublic( accessor ) && isNotStatic( accessor );
} }
public static boolean isPresenceCheckMethod(Accessor method) { static boolean isPublic(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) {
return method.getModifiers().contains( Modifier.PUBLIC ); return method.getModifiers().contains( Modifier.PUBLIC );
} }
@ -137,12 +92,6 @@ public class Executables {
return accessor != null && accessor.getModifiers().contains( Modifier.FINAL ); 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) { public static boolean isDefaultMethod(ExecutableElement method) {
try { try {
return DEFAULT_METHOD != null && Boolean.TRUE.equals( DEFAULT_METHOD.invoke( method ) ); 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 * @param mirror the type mirror
* *
@ -356,33 +295,4 @@ public class Executables {
public static boolean isBeforeMappingMethod(ExecutableElement executableElement) { public static boolean isBeforeMappingMethod(ExecutableElement executableElement) {
return BeforeMappingPrism.getInstanceOn( executableElement ) != null; 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() { 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>(); List<Accessor> getterMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) { for ( Accessor method : elements ) {
if ( Executables.isGetterMethod( method ) ) { if ( accessorNaming.isGetterMethod( method ) ) {
getterMethods.add( method ); getterMethods.add( method );
} }
} }
@ -60,11 +60,12 @@ public class Filters {
return fieldAccessors; 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>(); List<ExecutableElementAccessor> presenceCheckMethods = new LinkedList<ExecutableElementAccessor>();
for ( Accessor method : elements ) { for ( Accessor method : elements ) {
if ( Executables.isPresenceCheckMethod( method ) ) { if ( accessorNaming.isPresenceCheckMethod( method ) ) {
presenceCheckMethods.add( (ExecutableElementAccessor) method ); presenceCheckMethods.add( (ExecutableElementAccessor) method );
} }
} }
@ -72,22 +73,22 @@ public class Filters {
return presenceCheckMethods; 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>(); List<Accessor> setterMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) { for ( Accessor method : elements ) {
if ( Executables.isSetterMethod( method ) ) { if ( accessorNaming.isSetterMethod( method ) ) {
setterMethods.add( method ); setterMethods.add( method );
} }
} }
return setterMethods; 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>(); List<Accessor> adderMethods = new LinkedList<Accessor>();
for ( Accessor method : elements ) { for ( Accessor method : elements ) {
if ( Executables.isAdderMethod( method ) ) { if ( accessorNaming.isAdderMethod( method ) ) {
adderMethods.add( method ); adderMethods.add( method );
} }
} }

View File

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

View File

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