This commit is contained in:
Gunnar Morling 2014-10-26 22:41:04 +01:00
parent 9ea7f96b9c
commit b560b953cf
3 changed files with 72 additions and 67 deletions

View File

@ -20,7 +20,6 @@ package org.mapstruct.ap.model;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.tools.Diagnostic; import javax.tools.Diagnostic;
import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Parameter;
@ -45,12 +44,12 @@ public class EnumMappingMethod extends MappingMethod {
private SourceMethod method; private SourceMethod method;
private MappingBuilderContext ctx; private MappingBuilderContext ctx;
public Builder mappingContext( MappingBuilderContext mappingContext ) { public Builder mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext; this.ctx = mappingContext;
return this; return this;
} }
public Builder souceMethod( SourceMethod sourceMethod ) { public Builder souceMethod(SourceMethod sourceMethod) {
this.method = sourceMethod; this.method = sourceMethod;
return this; return this;
} }
@ -58,14 +57,14 @@ public class EnumMappingMethod extends MappingMethod {
public EnumMappingMethod build() { public EnumMappingMethod build() {
if ( !reportErrorIfMappedEnumConstantsDontExist( method ) if ( !reportErrorIfMappedEnumConstantsDontExist( method )
|| !reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped( method ) ) { || !reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped( method ) ) {
return null; return null;
} }
List<EnumMapping> enumMappings = new ArrayList<EnumMapping>(); List<EnumMapping> enumMappings = new ArrayList<EnumMapping>();
List<String> sourceEnumConstants List<String> sourceEnumConstants
= method.getSourceParameters().iterator().next().getType().getEnumConstants(); = method.getSourceParameters().iterator().next().getType().getEnumConstants();
for ( String enumConstant : sourceEnumConstants ) { for ( String enumConstant : sourceEnumConstants ) {
List<Mapping> mappedConstants = method.getMappingBySourcePropertyName( enumConstant ); List<Mapping> mappedConstants = method.getMappingBySourcePropertyName( enumConstant );
@ -74,8 +73,11 @@ public class EnumMappingMethod extends MappingMethod {
enumMappings.add( new EnumMapping( enumConstant, enumConstant ) ); enumMappings.add( new EnumMapping( enumConstant, enumConstant ) );
} }
else if ( mappedConstants.size() == 1 ) { else if ( mappedConstants.size() == 1 ) {
enumMappings.add( new EnumMapping( enumMappings.add(
enumConstant, mappedConstants.iterator().next().getTargetName() ) ); new EnumMapping(
enumConstant, mappedConstants.iterator().next().getTargetName()
)
);
} }
else { else {
List<String> targetConstants = new ArrayList<String>( mappedConstants.size() ); List<String> targetConstants = new ArrayList<String>( mappedConstants.size() );
@ -83,14 +85,14 @@ public class EnumMappingMethod extends MappingMethod {
targetConstants.add( mapping.getTargetName() ); targetConstants.add( mapping.getTargetName() );
} }
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
String.format( String.format(
"One enum constant must not be mapped to more than one target constant, " "One enum constant must not be mapped to more than one target constant, "
+ "but constant %s is mapped to %s.", + "but constant %s is mapped to %s.",
enumConstant, enumConstant,
Strings.join( targetConstants, ", " ) Strings.join( targetConstants, ", " )
), ),
method.getExecutable() method.getExecutable()
); );
} }
} }
@ -98,14 +100,14 @@ public class EnumMappingMethod extends MappingMethod {
return new EnumMappingMethod( method, enumMappings ); return new EnumMappingMethod( method, enumMappings );
} }
private boolean reportErrorIfMappedEnumConstantsDontExist( SourceMethod method ) { private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) {
// only report errors if this method itself is configured // only report errors if this method itself is configured
if ( method.isConfiguredByReverseMappingMethod() ) { if ( method.isConfiguredByReverseMappingMethod() ) {
return true; return true;
} }
List<String> sourceEnumConstants = List<String> sourceEnumConstants =
method.getSourceParameters().iterator().next().getType().getEnumConstants(); method.getSourceParameters().iterator().next().getType().getEnumConstants();
List<String> targetEnumConstants = method.getReturnType().getEnumConstants(); List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
boolean foundIncorrectMapping = false; boolean foundIncorrectMapping = false;
@ -114,47 +116,47 @@ public class EnumMappingMethod extends MappingMethod {
for ( Mapping mappedConstant : mappedConstants ) { for ( Mapping mappedConstant : mappedConstants ) {
if ( mappedConstant.getSourceName() == null ) { if ( mappedConstant.getSourceName() == null ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
"A source constant must be specified for mappings of an enum mapping method.", "A source constant must be specified for mappings of an enum mapping method.",
method.getExecutable(), method.getExecutable(),
mappedConstant.getMirror() mappedConstant.getMirror()
); );
foundIncorrectMapping = true; foundIncorrectMapping = true;
} }
else if ( !sourceEnumConstants.contains( mappedConstant.getSourceName() ) ) { else if ( !sourceEnumConstants.contains( mappedConstant.getSourceName() ) ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
String.format( String.format(
"Constant %s doesn't exist in enum type %s.", "Constant %s doesn't exist in enum type %s.",
mappedConstant.getSourceName(), mappedConstant.getSourceName(),
method.getSourceParameters().iterator().next().getType() method.getSourceParameters().iterator().next().getType()
), ),
method.getExecutable(), method.getExecutable(),
mappedConstant.getMirror(), mappedConstant.getMirror(),
mappedConstant.getSourceAnnotationValue() mappedConstant.getSourceAnnotationValue()
); );
foundIncorrectMapping = true; foundIncorrectMapping = true;
} }
if ( mappedConstant.getTargetName() == null ) { if ( mappedConstant.getTargetName() == null ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
"A target constant must be specified for mappings of an enum mapping method.", "A target constant must be specified for mappings of an enum mapping method.",
method.getExecutable(), method.getExecutable(),
mappedConstant.getMirror() mappedConstant.getMirror()
); );
foundIncorrectMapping = true; foundIncorrectMapping = true;
} }
else if ( !targetEnumConstants.contains( mappedConstant.getTargetName() ) ) { else if ( !targetEnumConstants.contains( mappedConstant.getTargetName() ) ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
String.format( String.format(
"Constant %s doesn't exist in enum type %s.", "Constant %s doesn't exist in enum type %s.",
mappedConstant.getTargetName(), mappedConstant.getTargetName(),
method.getReturnType() method.getReturnType()
), ),
method.getExecutable(), method.getExecutable(),
mappedConstant.getMirror(), mappedConstant.getMirror(),
mappedConstant.getTargetAnnotationValue() mappedConstant.getTargetAnnotationValue()
); );
foundIncorrectMapping = true; foundIncorrectMapping = true;
} }
@ -165,29 +167,29 @@ public class EnumMappingMethod extends MappingMethod {
} }
private boolean reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped( private boolean reportErrorIfSourceEnumConstantsWithoutCorrespondingTargetConstantAreNotMapped(
SourceMethod method ) { SourceMethod method) {
List<String> sourceEnumConstants = List<String> sourceEnumConstants =
method.getSourceParameters().iterator().next().getType().getEnumConstants(); method.getSourceParameters().iterator().next().getType().getEnumConstants();
List<String> targetEnumConstants = method.getReturnType().getEnumConstants(); List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
List<String> unmappedSourceEnumConstants = new ArrayList<String>(); List<String> unmappedSourceEnumConstants = new ArrayList<String>();
for ( String sourceEnumConstant : sourceEnumConstants ) { for ( String sourceEnumConstant : sourceEnumConstants ) {
if ( !targetEnumConstants.contains( sourceEnumConstant ) if ( !targetEnumConstants.contains( sourceEnumConstant )
&& method.getMappingBySourcePropertyName( sourceEnumConstant ).isEmpty() ) { && method.getMappingBySourcePropertyName( sourceEnumConstant ).isEmpty() ) {
unmappedSourceEnumConstants.add( sourceEnumConstant ); unmappedSourceEnumConstants.add( sourceEnumConstant );
} }
} }
if ( !unmappedSourceEnumConstants.isEmpty() ) { if ( !unmappedSourceEnumConstants.isEmpty() ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
String.format( String.format(
"The following constants from the source enum have no corresponding constant in the " "The following constants from the source enum have no corresponding constant in the "
+ "target enum and must be be mapped via @Mapping: %s", + "target enum and must be be mapped via @Mapping: %s",
Strings.join( unmappedSourceEnumConstants, ", " ) Strings.join( unmappedSourceEnumConstants, ", " )
), ),
method.getExecutable() method.getExecutable()
); );
} }
@ -196,7 +198,7 @@ public class EnumMappingMethod extends MappingMethod {
} }
private EnumMappingMethod( Method method, List<EnumMapping> enumMappings ) { private EnumMappingMethod(Method method, List<EnumMapping> enumMappings) {
super( method ); super( method );
this.enumMappings = enumMappings; this.enumMappings = enumMappings;
} }

View File

@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier; import javax.lang.model.element.Modifier;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
@ -76,7 +75,8 @@ public class SourceMethod implements Method {
mappings, mappings,
iterableMapping, iterableMapping,
mapMapping, mapMapping,
typeUtils ); typeUtils
);
} }
public static SourceMethod forReferencedMethod(Type declaringMapper, ExecutableElement executable, public static SourceMethod forReferencedMethod(Type declaringMapper, ExecutableElement executable,
@ -89,10 +89,11 @@ public class SourceMethod implements Method {
parameters, parameters,
returnType, returnType,
exceptionTypes, exceptionTypes,
Collections.<String, List<Mapping>> emptyMap(), Collections.<String, List<Mapping>>emptyMap(),
null, null,
null, null,
typeUtils ); typeUtils
);
} }
public static SourceMethod forFactoryMethod(Type declaringMapper, ExecutableElement executable, Type returnType, public static SourceMethod forFactoryMethod(Type declaringMapper, ExecutableElement executable, Type returnType,
@ -101,13 +102,14 @@ public class SourceMethod implements Method {
return new SourceMethod( return new SourceMethod(
declaringMapper, declaringMapper,
executable, executable,
Collections.<Parameter> emptyList(), Collections.<Parameter>emptyList(),
returnType, returnType,
exceptionTypes, exceptionTypes,
Collections.<String, List<Mapping>> emptyMap(), Collections.<String, List<Mapping>>emptyMap(),
null, null,
null, null,
typeUtils ); typeUtils
);
} }
private SourceMethod(Type declaringMapper, ExecutableElement executable, List<Parameter> parameters, private SourceMethod(Type declaringMapper, ExecutableElement executable, List<Parameter> parameters,
@ -214,7 +216,7 @@ public class SourceMethod implements Method {
/** /**
* @return the {@link Mapping}s configured for this method, keyed by target property name. Only for enum mapping * @return the {@link Mapping}s configured for this method, keyed by target property name. Only for enum mapping
* methods a target will be mapped by several sources. * methods a target will be mapped by several sources.
*/ */
public Map<String, List<Mapping>> getMappings() { public Map<String, List<Mapping>> getMappings() {
return mappings; return mappings;
@ -352,6 +354,7 @@ public class SourceMethod implements Method {
/** /**
* @param parameters the parameter list to check * @param parameters the parameter list to check
*
* @return <code>true</code>, iff the parameter list contains a parameter annotated with {@code @TargetType} * @return <code>true</code>, iff the parameter list contains a parameter annotated with {@code @TargetType}
*/ */
public static boolean containsTargetTypeParameter(List<Parameter> parameters) { public static boolean containsTargetTypeParameter(List<Parameter> parameters) {

View File

@ -18,13 +18,10 @@
*/ */
package org.mapstruct.ap.test.source.constants; package org.mapstruct.ap.test.source.constants;
import static org.fest.assertions.Assertions.assertThat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.Kind;
import org.junit.Test; import org.junit.Test;
@ -36,6 +33,8 @@ import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.fest.assertions.Assertions.assertThat;
/** /**
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@ -124,8 +123,9 @@ public class SourceConstantsTest {
@Diagnostic(type = ErroneousMapper3.class, @Diagnostic(type = ErroneousMapper3.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 41, line = 41,
messageRegExp = "Expression and constant are both defined in @Mapping, either define an expression or a " messageRegExp =
+ "constant"), "Expression and constant are both defined in @Mapping, either define an expression or a "
+ "constant"),
@Diagnostic(type = ErroneousMapper3.class, @Diagnostic(type = ErroneousMapper3.class,
kind = Kind.WARNING, kind = Kind.WARNING,
line = 41, line = 41,