mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
* #1557 making enum-to-string and string-to-enum * #1936 <ANY_REMAINING> and <ANY_UNMAPPED> not ignored when inverting
This commit is contained in:
parent
44ae27d7ca
commit
507ec1b384
@ -23,11 +23,16 @@ public final class MappingConstants {
|
||||
/**
|
||||
* In an {@link ValueMapping} this represents any source that is not already mapped by either a defined mapping or
|
||||
* by means of name based mapping.
|
||||
*
|
||||
* NOTE: The value is only applicable to {@link ValueMapping#source()} and not to {@link ValueMapping#target()}.
|
||||
*/
|
||||
public static final String ANY_REMAINING = "<ANY_REMAINING>";
|
||||
|
||||
/**
|
||||
* In an {@link ValueMapping} this represents any source that is not already mapped by a defined mapping.
|
||||
*
|
||||
* NOTE: The value is only applicable to {@link ValueMapping#source()} and not to {@link ValueMapping#target()}.
|
||||
*
|
||||
*/
|
||||
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
[[mapping-enum-types]]
|
||||
== Mapping Values
|
||||
|
||||
=== Mapping enum types
|
||||
=== Mapping enum to enum types
|
||||
|
||||
MapStruct supports the generation of methods which map one Java enum type into another.
|
||||
|
||||
@ -67,7 +67,7 @@ public class OrderMapperImpl implements OrderMapper {
|
||||
By default an error will be raised by MapStruct in case a constant of the source enum type does not have a corresponding constant with the same name in the target type and also is not mapped to another constant via `@ValueMapping`. This ensures that all constants are mapped in a safe and predictable manner. The generated
|
||||
mapping method will throw an IllegalStateException if for some reason an unrecognized source value occurs.
|
||||
|
||||
MapStruct also has a mechanism for mapping any remaining (unspecified) mappings to a default. This can be used only once in a set of value mappings. It comes in two flavors: `<ANY_REMAINING>` and `<ANY_UNMAPPED>`.
|
||||
MapStruct also has a mechanism for mapping any remaining (unspecified) mappings to a default. This can be used only once in a set of value mappings and only applies to the source. It comes in two flavors: `<ANY_REMAINING>` and `<ANY_UNMAPPED>`. They cannot be used at the same time.
|
||||
|
||||
In case of source `<ANY_REMAINING>` MapStruct will continue to map a source enum constant to a target enum constant with the same name. The remainder of the source enum constants will be mapped to the target specified in the `@ValueMapping` with `<ANY_REMAINING>` source.
|
||||
|
||||
@ -80,7 +80,7 @@ MapStruct is able to handle `null` sources and `null` targets by means of the `<
|
||||
Constants for `<ANY_REMAINING>`, `<ANY_UNMAPPED>` and `<NULL>` are available in the `MappingConstants` class.
|
||||
====
|
||||
|
||||
Finally `@InheritInverseConfiguration` and `@InheritConfiguration` can be used in combination with `@ValueMappings`.
|
||||
Finally `@InheritInverseConfiguration` and `@InheritConfiguration` can be used in combination with `@ValueMappings`. `<ANY_REMAINING>` and `<ANY_UNMAPPED>` will be ignored in that case.
|
||||
|
||||
.Enum mapping method, <NULL> and <ANY_REMAINING>
|
||||
====
|
||||
@ -140,4 +140,22 @@ public class SpecialOrderMapperImpl implements SpecialOrderMapper {
|
||||
[WARNING]
|
||||
====
|
||||
The mapping of enum to enum via the `@Mapping` annotation is *DEPRECATED*. It will be removed from future versions of MapStruct. Please adapt existing enum mapping methods to make use of `@ValueMapping` instead.
|
||||
====
|
||||
====
|
||||
|
||||
=== Mapping enum-to-String or String-to-enum
|
||||
|
||||
MapStruct supports enum to a String mapping along the same lines as is described in <<Mapping enum to enum types, enum-to-enum types>>. There are similarities and differences:
|
||||
|
||||
*enum to `String`*
|
||||
|
||||
1. Similarity: All not explicit defined mappings will result in each source enum constant value being mapped a `String` value with the same constant value.
|
||||
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
||||
3. Difference: `<ANY_REMAINING>` will result in an error. It acts on the premise that there is name similarity between enum constants in source and target which does not make sense for a String type.
|
||||
4. Difference: Given 1. and 3. there will never be unmapped values.
|
||||
|
||||
*`String` to enum*
|
||||
|
||||
1. Similarity: All not explicit defined mappings will result in the target enum constant mapped from the `String` value when that maches the target enum constant name.
|
||||
2. Similarity: `<ANY_UNMAPPED`> stops after handling defined mapping and proceeds to the switch/default clause value.
|
||||
3. Similarity: `<ANY_REMAINING>` will create a mapping for each target enum constant and proceed to the switch/default clause value.
|
||||
4. Difference: A switch/default value needs to be provided to have a determined outcome (enum has a limited set of values, `String` has unlimited options). Failing to specify `<ANY_REMAINING>` or `<ANY_UNMAPPED`> will result in a warning.
|
||||
|
@ -5,6 +5,9 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model;
|
||||
|
||||
import static org.mapstruct.ap.internal.prism.MappingConstantsPrism.ANY_REMAINING;
|
||||
import static org.mapstruct.ap.internal.prism.MappingConstantsPrism.ANY_UNMAPPED;
|
||||
import static org.mapstruct.ap.internal.prism.MappingConstantsPrism.NULL;
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -16,11 +19,11 @@ import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.ValueMapping;
|
||||
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.MappingConstantsPrism;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
|
||||
@ -42,10 +45,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
|
||||
private Method method;
|
||||
private MappingBuilderContext ctx;
|
||||
private final List<ValueMapping> trueValueMappings = new ArrayList<>();
|
||||
private ValueMapping defaultTargetValue = null;
|
||||
private ValueMapping nullTargetValue = null;
|
||||
private boolean applyNamebasedMappings = true;
|
||||
private ValueMappings valueMappings;
|
||||
|
||||
public Builder mappingContext(MappingBuilderContext mappingContext) {
|
||||
this.ctx = mappingContext;
|
||||
@ -58,21 +58,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
|
||||
public Builder valueMappings(List<ValueMapping> valueMappings) {
|
||||
for ( ValueMapping valueMapping : valueMappings ) {
|
||||
if ( MappingConstantsPrism.ANY_REMAINING.equals( valueMapping.getSource() ) ) {
|
||||
defaultTargetValue = valueMapping;
|
||||
}
|
||||
else if ( MappingConstantsPrism.ANY_UNMAPPED.equals( valueMapping.getSource() ) ) {
|
||||
defaultTargetValue = valueMapping;
|
||||
applyNamebasedMappings = false;
|
||||
}
|
||||
else if ( MappingConstantsPrism.NULL.equals( valueMapping.getSource() ) ) {
|
||||
nullTargetValue = valueMapping;
|
||||
}
|
||||
else {
|
||||
trueValueMappings.add( valueMapping );
|
||||
}
|
||||
}
|
||||
this.valueMappings = new ValueMappings( valueMappings );
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -80,27 +66,19 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
|
||||
// initialize all relevant parameters
|
||||
List<MappingEntry> mappingEntries = new ArrayList<>();
|
||||
String nullTarget = null;
|
||||
String defaultTarget = null;
|
||||
boolean throwIllegalArgumentException = false;
|
||||
|
||||
// for now, we're only dealing with enum mappings, populate relevant parameters based on enum-2-enum
|
||||
if ( first( method.getSourceParameters() ).getType().isEnumType() && method.getResultType().isEnumType() ) {
|
||||
mappingEntries.addAll( enumToEnumMapping( method ) );
|
||||
|
||||
if ( (nullTargetValue != null) && !MappingConstantsPrism.NULL.equals( nullTargetValue.getTarget() ) ) {
|
||||
// absense nulltargetvalue reverts to null. Or it could be a deliberate choice to return null
|
||||
nullTarget = nullTargetValue.getTarget();
|
||||
}
|
||||
if ( defaultTargetValue != null ) {
|
||||
// If the default target value is NULL then we should map it to null
|
||||
defaultTarget = MappingConstantsPrism.NULL.equals( defaultTargetValue.getTarget() ) ? null :
|
||||
defaultTargetValue.getTarget();
|
||||
}
|
||||
else {
|
||||
throwIllegalArgumentException = true;
|
||||
}
|
||||
Type sourceType = first( method.getSourceParameters() ).getType();
|
||||
Type targetType = method.getResultType();
|
||||
|
||||
// enum-to-enum
|
||||
if ( sourceType.isEnumType() && targetType.isEnumType() ) {
|
||||
mappingEntries.addAll( enumToEnumMapping( method, sourceType, targetType ) );
|
||||
}
|
||||
else if ( sourceType.isEnumType() && targetType.isString() ) {
|
||||
mappingEntries.addAll( enumToStringMapping( method, sourceType ) );
|
||||
}
|
||||
else if ( sourceType.isString() && targetType.isEnumType() ) {
|
||||
mappingEntries.addAll( stringToEnumMapping( method, targetType ) );
|
||||
}
|
||||
|
||||
// do before / after lifecycle mappings
|
||||
@ -112,32 +90,36 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
LifecycleMethodResolver.afterMappingMethods( method, selectionParameters, ctx, existingVariables );
|
||||
|
||||
// finally return a mapping
|
||||
return new ValueMappingMethod( method, mappingEntries, nullTarget, defaultTarget,
|
||||
throwIllegalArgumentException, beforeMappingMethods, afterMappingMethods );
|
||||
return new ValueMappingMethod( method,
|
||||
mappingEntries,
|
||||
valueMappings.nullValueTarget,
|
||||
valueMappings.defaultTargetValue,
|
||||
!valueMappings.hasDefaultValue,
|
||||
beforeMappingMethods,
|
||||
afterMappingMethods
|
||||
);
|
||||
}
|
||||
|
||||
private List<MappingEntry> enumToEnumMapping(Method method) {
|
||||
private List<MappingEntry> enumToEnumMapping(Method method, Type sourceType, Type targetType ) {
|
||||
|
||||
List<MappingEntry> mappings = new ArrayList<>();
|
||||
List<String> unmappedSourceConstants
|
||||
= new ArrayList<>( first( method.getSourceParameters() ).getType().getEnumConstants() );
|
||||
|
||||
|
||||
if ( !reportErrorIfMappedEnumConstantsDontExist( method ) ) {
|
||||
List<String> unmappedSourceConstants = new ArrayList<>( sourceType.getEnumConstants() );
|
||||
boolean sourceErrorOccurred = !reportErrorIfMappedSourceEnumConstantsDontExist( method, sourceType );
|
||||
boolean targetErrorOccurred = !reportErrorIfMappedTargetEnumConstantsDontExist( method, targetType );
|
||||
if ( sourceErrorOccurred || targetErrorOccurred ) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
// Start to fill the mappings with the defined valuemappings
|
||||
for ( ValueMapping valueMapping : trueValueMappings ) {
|
||||
// Start to fill the mappings with the defined value mappings
|
||||
for ( ValueMapping valueMapping : valueMappings.regularValueMappings ) {
|
||||
String target =
|
||||
MappingConstantsPrism.NULL.equals( valueMapping.getTarget() ) ? null : valueMapping.getTarget();
|
||||
NULL.equals( valueMapping.getTarget() ) ? null : valueMapping.getTarget();
|
||||
mappings.add( new MappingEntry( valueMapping.getSource(), target ) );
|
||||
unmappedSourceConstants.remove( valueMapping.getSource() );
|
||||
}
|
||||
|
||||
|
||||
// add mappings based on name
|
||||
if ( applyNamebasedMappings ) {
|
||||
if ( !valueMappings.hasMapAnyUnmapped ) {
|
||||
|
||||
// get all target constants
|
||||
List<String> targetConstants = method.getReturnType().getEnumConstants();
|
||||
@ -148,7 +130,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
if ( defaultTargetValue == null && !unmappedSourceConstants.isEmpty() ) {
|
||||
if ( valueMappings.defaultTarget == null && !unmappedSourceConstants.isEmpty() ) {
|
||||
String sourceErrorMessage = "source";
|
||||
String targetErrorMessage = "target";
|
||||
if ( method instanceof ForgedMethod && ( (ForgedMethod) method ).getHistory() != null ) {
|
||||
@ -160,7 +142,7 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
// all sources should now be matched, there's no default to fall back to, so if sources remain,
|
||||
// we have an issue.
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
Message.VALUE_MAPPING_UNMAPPED_SOURCES,
|
||||
Message.VALUEMAPPING_UNMAPPED_SOURCES,
|
||||
sourceErrorMessage,
|
||||
targetErrorMessage,
|
||||
Strings.join( unmappedSourceConstants, ", " )
|
||||
@ -171,6 +153,64 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private List<MappingEntry> enumToStringMapping(Method method, Type sourceType ) {
|
||||
|
||||
List<MappingEntry> mappings = new ArrayList<>();
|
||||
List<String> unmappedSourceConstants = new ArrayList<>( sourceType.getEnumConstants() );
|
||||
boolean sourceErrorOccurred = !reportErrorIfMappedSourceEnumConstantsDontExist( method, sourceType );
|
||||
boolean anyRemainingUsedError = !reportErrorIfSourceEnumConstantsContainsAnyRemaining( method );
|
||||
if ( sourceErrorOccurred || anyRemainingUsedError ) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
// Start to fill the mappings with the defined valuemappings
|
||||
for ( ValueMapping valueMapping : valueMappings.regularValueMappings ) {
|
||||
String target =
|
||||
NULL.equals( valueMapping.getTarget() ) ? null : valueMapping.getTarget();
|
||||
mappings.add( new MappingEntry( valueMapping.getSource(), target ) );
|
||||
unmappedSourceConstants.remove( valueMapping.getSource() );
|
||||
}
|
||||
|
||||
// add mappings based on name
|
||||
if ( !valueMappings.hasMapAnyUnmapped ) {
|
||||
|
||||
// all remaining constants are mapped
|
||||
for ( String sourceConstant : unmappedSourceConstants ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
|
||||
}
|
||||
}
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private List<MappingEntry> stringToEnumMapping(Method method, Type targetType ) {
|
||||
|
||||
List<MappingEntry> mappings = new ArrayList<>();
|
||||
List<String> unmappedSourceConstants = new ArrayList<>( targetType.getEnumConstants() );
|
||||
boolean sourceErrorOccurred = !reportErrorIfMappedTargetEnumConstantsDontExist( method, targetType );
|
||||
boolean mandatoryMissing = !reportErrorIfAnyRemainingOrAnyUnMappedMissing( method );
|
||||
if ( sourceErrorOccurred || mandatoryMissing ) {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
// Start to fill the mappings with the defined valuemappings
|
||||
for ( ValueMapping valueMapping : valueMappings.regularValueMappings ) {
|
||||
String target =
|
||||
NULL.equals( valueMapping.getTarget() ) ? null : valueMapping.getTarget();
|
||||
mappings.add( new MappingEntry( valueMapping.getSource(), target ) );
|
||||
unmappedSourceConstants.remove( valueMapping.getSource() );
|
||||
}
|
||||
|
||||
// add mappings based on name
|
||||
if ( !valueMappings.hasMapAnyUnmapped ) {
|
||||
|
||||
// all remaining constants are mapped
|
||||
for ( String sourceConstant : unmappedSourceConstants ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
|
||||
}
|
||||
}
|
||||
return mappings;
|
||||
}
|
||||
|
||||
private SelectionParameters getSelectionParameters(Method method, Types typeUtils) {
|
||||
BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() );
|
||||
if ( beanMappingPrism != null ) {
|
||||
@ -182,13 +222,12 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean reportErrorIfMappedEnumConstantsDontExist(Method method) {
|
||||
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
|
||||
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
|
||||
private boolean reportErrorIfMappedSourceEnumConstantsDontExist(Method method, Type sourceType) {
|
||||
List<String> sourceEnumConstants = sourceType.getEnumConstants();
|
||||
|
||||
boolean foundIncorrectMapping = false;
|
||||
|
||||
for ( ValueMapping mappedConstant : trueValueMappings ) {
|
||||
for ( ValueMapping mappedConstant : valueMappings.regularValueMappings ) {
|
||||
|
||||
if ( !sourceEnumConstants.contains( mappedConstant.getSource() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
@ -196,11 +235,50 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
mappedConstant.getSourceAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
mappedConstant.getSource(),
|
||||
first( method.getSourceParameters() ).getType()
|
||||
sourceType
|
||||
);
|
||||
foundIncorrectMapping = true;
|
||||
}
|
||||
if ( !MappingConstantsPrism.NULL.equals( mappedConstant.getTarget() )
|
||||
}
|
||||
return !foundIncorrectMapping;
|
||||
}
|
||||
|
||||
private boolean reportErrorIfSourceEnumConstantsContainsAnyRemaining(Method method) {
|
||||
boolean foundIncorrectMapping = false;
|
||||
|
||||
if ( valueMappings.hasMapAnyRemaining ) {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
valueMappings.defaultTarget.getMirror(),
|
||||
valueMappings.defaultTarget.getSourceAnnotationValue(),
|
||||
Message.VALUEMAPPING_ANY_REMAINING_FOR_NON_ENUM,
|
||||
method.getResultType()
|
||||
);
|
||||
foundIncorrectMapping = true;
|
||||
}
|
||||
return !foundIncorrectMapping;
|
||||
}
|
||||
|
||||
private boolean reportErrorIfAnyRemainingOrAnyUnMappedMissing(Method method) {
|
||||
boolean foundIncorrectMapping = false;
|
||||
|
||||
if ( !( valueMappings.hasMapAnyUnmapped || valueMappings.hasMapAnyRemaining ) ) {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
Message.VALUEMAPPING_ANY_REMAINING_OR_UNMAPPED_MISSING
|
||||
);
|
||||
foundIncorrectMapping = true;
|
||||
}
|
||||
return !foundIncorrectMapping;
|
||||
}
|
||||
|
||||
private boolean reportErrorIfMappedTargetEnumConstantsDontExist(Method method, Type targetType) {
|
||||
List<String> targetEnumConstants = targetType.getEnumConstants();
|
||||
|
||||
boolean foundIncorrectMapping = false;
|
||||
|
||||
for ( ValueMapping mappedConstant : valueMappings.regularValueMappings ) {
|
||||
if ( !NULL.equals( mappedConstant.getTarget() )
|
||||
&& !targetEnumConstants.contains( mappedConstant.getTarget() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
mappedConstant.getMirror(),
|
||||
@ -213,25 +291,25 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
if ( defaultTargetValue != null && !MappingConstantsPrism.NULL.equals( defaultTargetValue.getTarget() )
|
||||
&& !targetEnumConstants.contains( defaultTargetValue.getTarget() ) ) {
|
||||
if ( valueMappings.defaultTarget != null && !NULL.equals( valueMappings.defaultTarget.getTarget() )
|
||||
&& !targetEnumConstants.contains( valueMappings.defaultTarget.getTarget() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
defaultTargetValue.getMirror(),
|
||||
defaultTargetValue.getTargetAnnotationValue(),
|
||||
valueMappings.defaultTarget.getMirror(),
|
||||
valueMappings.defaultTarget.getTargetAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
defaultTargetValue.getTarget(),
|
||||
valueMappings.defaultTarget.getTarget(),
|
||||
method.getReturnType()
|
||||
);
|
||||
foundIncorrectMapping = true;
|
||||
}
|
||||
|
||||
if ( nullTargetValue != null && MappingConstantsPrism.NULL.equals( nullTargetValue.getTarget() )
|
||||
&& !targetEnumConstants.contains( nullTargetValue.getTarget() ) ) {
|
||||
if ( valueMappings.nullTarget != null && NULL.equals( valueMappings.nullTarget.getTarget() )
|
||||
&& !targetEnumConstants.contains( valueMappings.nullTarget.getTarget() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
nullTargetValue.getMirror(),
|
||||
nullTargetValue.getTargetAnnotationValue(),
|
||||
valueMappings.nullTarget.getMirror(),
|
||||
valueMappings.nullTarget.getTargetAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
nullTargetValue.getTarget(),
|
||||
valueMappings.nullTarget.getTarget(),
|
||||
method.getReturnType()
|
||||
);
|
||||
foundIncorrectMapping = true;
|
||||
@ -241,6 +319,47 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ValueMappings {
|
||||
|
||||
List<ValueMapping> regularValueMappings = new ArrayList<>();
|
||||
ValueMapping defaultTarget = null;
|
||||
String defaultTargetValue = null;
|
||||
ValueMapping nullTarget = null;
|
||||
String nullValueTarget = null;
|
||||
boolean hasMapAnyUnmapped = false;
|
||||
boolean hasMapAnyRemaining = false;
|
||||
boolean hasDefaultValue = false;
|
||||
|
||||
ValueMappings(List<ValueMapping> valueMappings) {
|
||||
|
||||
for ( ValueMapping valueMapping : valueMappings ) {
|
||||
if ( ANY_REMAINING.equals( valueMapping.getSource() ) ) {
|
||||
defaultTarget = valueMapping;
|
||||
defaultTargetValue = getValue( defaultTarget );
|
||||
hasDefaultValue = true;
|
||||
hasMapAnyRemaining = true;
|
||||
}
|
||||
else if ( ANY_UNMAPPED.equals( valueMapping.getSource() ) ) {
|
||||
defaultTarget = valueMapping;
|
||||
defaultTargetValue = getValue( defaultTarget );
|
||||
hasDefaultValue = true;
|
||||
hasMapAnyUnmapped = true;
|
||||
}
|
||||
else if ( NULL.equals( valueMapping.getSource() ) ) {
|
||||
nullTarget = valueMapping;
|
||||
nullValueTarget = getValue( nullTarget );
|
||||
}
|
||||
else {
|
||||
regularValueMappings.add( valueMapping );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String getValue(ValueMapping valueMapping) {
|
||||
return NULL.equals( valueMapping.getTarget() ) ? null : valueMapping.getTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private ValueMappingMethod(Method method, List<MappingEntry> enumMappings, String nullTarget, String defaultTarget,
|
||||
boolean throwIllegalArgumentException, List<LifecycleCallbackMethodReference> beforeMappingMethods,
|
||||
List<LifecycleCallbackMethodReference> afterMappingMethods) {
|
||||
|
@ -220,6 +220,10 @@ public class Type extends ModelElement implements Comparable<Type> {
|
||||
return typeElement != null && typeElement.getModifiers().contains( Modifier.ABSTRACT );
|
||||
}
|
||||
|
||||
public boolean isString() {
|
||||
return String.class.getName().equals( getFullyQualifiedName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return this type's enum constants in case it is an enum, an empty list otherwise.
|
||||
*/
|
||||
|
@ -5,6 +5,8 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model.source;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||
|
||||
/**
|
||||
@ -18,18 +20,34 @@ public final class MappingMethodUtils {
|
||||
private MappingMethodUtils() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the provided {@code method} is for enum mapping. A Method is an Enum Mapping method when the
|
||||
* source parameter and result type are enum types.
|
||||
* <ol>
|
||||
* <li>source parameter type and result type are enum types</li>
|
||||
* <li>source parameter type is a String and result type is an enum type</li>
|
||||
* <li>source parameter type is a enum type and result type is a String</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param method to check
|
||||
*
|
||||
* @return {@code true} if the method is for enum mapping, {@code false} otherwise
|
||||
*/
|
||||
public static boolean isEnumMapping(Method method) {
|
||||
return method.getSourceParameters().size() == 1
|
||||
&& first( method.getSourceParameters() ).getType().isEnumType()
|
||||
&& method.getResultType().isEnumType();
|
||||
if ( method.getSourceParameters().size() != 1 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Type source = first( method.getSourceParameters() ).getType();
|
||||
Type result = method.getResultType();
|
||||
if ( source.isEnumType() && result.isEnumType() ) {
|
||||
return true;
|
||||
}
|
||||
if ( source.isString() && result.isEnumType() ) {
|
||||
return true;
|
||||
}
|
||||
if ( source.isEnumType() && result.isString() ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,18 @@ package org.mapstruct.ap.internal.model.source;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
import org.mapstruct.ap.internal.prism.MappingConstantsPrism;
|
||||
import org.mapstruct.ap.internal.prism.ValueMappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.ValueMappingsPrism;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
|
||||
import static org.mapstruct.ap.internal.prism.MappingConstantsPrism.ANY_REMAINING;
|
||||
import static org.mapstruct.ap.internal.prism.MappingConstantsPrism.ANY_UNMAPPED;
|
||||
|
||||
/**
|
||||
* Represents the mapping between one value constant and another.
|
||||
*
|
||||
@ -51,8 +52,8 @@ public class ValueMapping {
|
||||
mappingPrism.source()
|
||||
);
|
||||
}
|
||||
if ( MappingConstantsPrism.ANY_REMAINING.equals( mapping.source )
|
||||
|| MappingConstantsPrism.ANY_UNMAPPED.equals( mapping.source ) ) {
|
||||
if ( ANY_REMAINING.equals( mapping.source )
|
||||
|| ANY_UNMAPPED.equals( mapping.source ) ) {
|
||||
if ( anyFound ) {
|
||||
messager.printMessage(
|
||||
method,
|
||||
@ -111,8 +112,7 @@ public class ValueMapping {
|
||||
|
||||
public ValueMapping inverse() {
|
||||
ValueMapping result;
|
||||
if ( !MappingConstantsPrism.ANY_REMAINING.equals( source )
|
||||
|| !MappingConstantsPrism.ANY_UNMAPPED.equals( source ) ) {
|
||||
if ( !(ANY_REMAINING.equals( source ) || ANY_UNMAPPED.equals( source ) ) ) {
|
||||
result = new ValueMapping(
|
||||
target,
|
||||
source,
|
||||
|
@ -461,12 +461,12 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( parameterType.isEnumType() && !resultType.isEnumType() ) {
|
||||
if ( parameterType.isEnumType() && !( resultType.isEnumType() || resultType.isString() ) ) {
|
||||
messager.printMessage( method, Message.RETRIEVAL_ENUM_TO_NON_ENUM );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !parameterType.isEnumType() && resultType.isEnumType() ) {
|
||||
if ( !( parameterType.isEnumType() || parameterType.isString() ) && resultType.isEnumType() ) {
|
||||
messager.printMessage( method, Message.RETRIEVAL_NON_ENUM_TO_ENUM );
|
||||
return false;
|
||||
}
|
||||
|
@ -152,7 +152,9 @@ public enum Message {
|
||||
VALUEMAPPING_CREATE_NOTE( "creating value mapping method implementation for %s.", Diagnostic.Kind.NOTE ),
|
||||
VALUEMAPPING_DUPLICATE_SOURCE( "Source value mapping: \"%s\" cannot be mapped more than once." ),
|
||||
VALUEMAPPING_ANY_AREADY_DEFINED( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once." ),
|
||||
VALUE_MAPPING_UNMAPPED_SOURCES( "The following constants from the %s enum have no corresponding constant in the %s enum and must be be mapped via adding additional mappings: %s." ),
|
||||
VALUEMAPPING_UNMAPPED_SOURCES( "The following constants from the %s enum have no corresponding constant in the %s enum and must be be mapped via adding additional mappings: %s." ),
|
||||
VALUEMAPPING_ANY_REMAINING_FOR_NON_ENUM( "Source = \"<ANY_REMAINING>\" can only be used on targets of type enum and not for %s." ),
|
||||
VALUEMAPPING_ANY_REMAINING_OR_UNMAPPED_MISSING( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" is advisable for mapping of type String to an enum type.", Diagnostic.Kind.WARNING ),
|
||||
VALUEMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s." );
|
||||
// CHECKSTYLE:ON
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
<#--
|
||||
|
||||
Copyright MapStruct Authors.
|
||||
|
||||
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
-->
|
||||
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.EnumMappingMethod" -->
|
||||
@Override
|
||||
public <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) {
|
||||
<#list beforeMappingReferencesWithoutMappingTarget as callback>
|
||||
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
|
||||
<#if !callback_has_next>
|
||||
|
||||
</#if>
|
||||
</#list>
|
||||
if ( ${sourceParameter.name} == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<@includeModel object=resultType/> ${resultName};
|
||||
|
||||
switch ( ${sourceParameter.name} ) {
|
||||
<#list enumMappings as enumMapping>
|
||||
case ${enumMapping.source}: ${resultName} = <@includeModel object=returnType/>.${enumMapping.target};
|
||||
break;
|
||||
</#list>
|
||||
default: throw new IllegalArgumentException( "Unexpected enum constant: " + ${sourceParameter.name} );
|
||||
}
|
||||
<#list beforeMappingReferencesWithMappingTarget as callback>
|
||||
<#if callback_index = 0>
|
||||
|
||||
</#if>
|
||||
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
|
||||
</#list>
|
||||
<#list afterMappingReferences as callback>
|
||||
<#if callback_index = 0>
|
||||
|
||||
</#if>
|
||||
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
|
||||
</#list>
|
||||
|
||||
return ${resultName};
|
||||
}
|
@ -15,17 +15,17 @@
|
||||
</#if>
|
||||
</#list>
|
||||
if ( ${sourceParameter.name} == null ) {
|
||||
return <#if nullTarget??><@includeModel object=returnType/>.${nullTarget}<#else>null</#if>;
|
||||
return <@writeTarget target=nullTarget/>;
|
||||
}
|
||||
|
||||
<@includeModel object=resultType/> ${resultName};
|
||||
|
||||
switch ( ${sourceParameter.name} ) {
|
||||
<#list valueMappings as valueMapping>
|
||||
case ${valueMapping.source}: ${resultName} = <#if valueMapping.target??><@includeModel object=returnType/>.${valueMapping.target}<#else>null</#if>;
|
||||
case <@writeSource source=valueMapping.source/>: ${resultName} = <@writeTarget target=valueMapping.target/>;
|
||||
break;
|
||||
</#list>
|
||||
default: <#if throwIllegalArgumentException>throw new IllegalArgumentException( "Unexpected enum constant: " + ${sourceParameter.name} )<#else>${resultName} = <#if defaultTarget??><@includeModel object=returnType/>.${defaultTarget}<#else>null</#if></#if>;
|
||||
default: <#if throwIllegalArgumentException>throw new IllegalArgumentException( "Unexpected enum constant: " + ${sourceParameter.name} )<#else>${resultName} = <@writeTarget target=defaultTarget/></#if>;
|
||||
}
|
||||
<#list beforeMappingReferencesWithMappingTarget as callback>
|
||||
<#if callback_index = 0>
|
||||
@ -40,5 +40,29 @@
|
||||
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
|
||||
</#list>
|
||||
|
||||
<#if !(valueMappings.empty && throwIllegalArgumentException)>
|
||||
return ${resultName};
|
||||
</#if>
|
||||
}
|
||||
<#macro writeSource source="">
|
||||
<@compress single_line=true>
|
||||
<#if sourceParameter.type.enumType>
|
||||
${source}
|
||||
<#elseif sourceParameter.type.string>
|
||||
"${source}"
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
||||
<#macro writeTarget target="">
|
||||
<@compress single_line=true>
|
||||
<#if target?has_content>
|
||||
<#if returnType.enumType>
|
||||
<@includeModel object=returnType/>.${target}
|
||||
<#elseif returnType.string>
|
||||
"${target}"
|
||||
</#if>
|
||||
<#else>
|
||||
null
|
||||
</#if>
|
||||
</@compress>
|
||||
</#macro>
|
@ -3,11 +3,13 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -12,6 +12,8 @@ import javax.tools.Diagnostic.Kind;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||
@ -214,7 +216,7 @@ public class EnumToEnumMappingTest {
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 25,
|
||||
line = 27,
|
||||
messageRegExp = "Source value mapping: \"EXTRA\" cannot be mapped more than once\\.")
|
||||
}
|
||||
)
|
||||
@ -228,11 +230,11 @@ public class EnumToEnumMappingTest {
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 24,
|
||||
line = 26,
|
||||
messageRegExp = "Constant FOO doesn't exist in enum type org.mapstruct.ap.test.value.OrderType\\."),
|
||||
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 25,
|
||||
line = 27,
|
||||
messageRegExp = "Constant BAR doesn't exist in enum type org.mapstruct.ap.test.value." +
|
||||
"ExternalOrderType\\.")
|
||||
}
|
||||
@ -247,7 +249,7 @@ public class EnumToEnumMappingTest {
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 21,
|
||||
line = 23,
|
||||
messageRegExp = "The following constants from the source enum have no corresponding constant in the " +
|
||||
"target enum and must be be mapped via adding additional mappings: EXTRA, STANDARD, NORMAL")
|
||||
}
|
||||
@ -262,7 +264,7 @@ public class EnumToEnumMappingTest {
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperDuplicateANY.class,
|
||||
kind = Kind.ERROR,
|
||||
line = 26,
|
||||
line = 28,
|
||||
messageRegExp = "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once\\." )
|
||||
}
|
||||
)
|
@ -3,11 +3,13 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,11 +3,13 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,9 +3,11 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,11 +3,13 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,8 +3,9 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
|
||||
/**
|
||||
* @author Gunnar Morling
|
@ -3,8 +3,9 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
|
||||
/**
|
||||
* @author Gunnar Morling
|
@ -3,12 +3,14 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
@ -12,6 +12,8 @@ import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.Named;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.enum2string;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@IssueKey( "1557" )
|
||||
@WithClasses({ OrderType.class, OrderMapper.class })
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class EnumToStringMappingTest {
|
||||
|
||||
@Test
|
||||
public void testTheNormalStuff() {
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( null ) ).isNull();
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( OrderType.EXTRA ) ).isEqualTo( "SPECIAL" );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( OrderType.STANDARD ) ).isEqualTo( "DEFAULT" );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( OrderType.NORMAL ) ).isEqualTo( "DEFAULT" );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( OrderType.B2B ) ).isEqualTo( "B2B" );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( OrderType.RETAIL ) ).isEqualTo( "RETAIL" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemainingAndNull() {
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( null ) ).isEqualTo( "DEFAULT" );
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( OrderType.STANDARD ) ).isNull();
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( OrderType.NORMAL ) ).isEqualTo( "SPECIAL" );
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( OrderType.B2B ) ).isEqualTo( "SPECIAL" );
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( OrderType.RETAIL ) ).isEqualTo( "SPECIAL" );
|
||||
assertThat( OrderMapper.INSTANCE.withAnyUnmappedAndNull( OrderType.EXTRA ) ).isEqualTo( "SPECIAL" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses(ErroneousOrderMapperUsingAnyRemaining.class)
|
||||
@ExpectedCompilationOutcome(
|
||||
value = CompilationResult.FAILED,
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperUsingAnyRemaining.class,
|
||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||
line = 26,
|
||||
messageRegExp = "\"<ANY_REMAINING>\" can only be used on targets of type enum and not for " +
|
||||
"java\\.lang\\.String\\.")
|
||||
}
|
||||
)
|
||||
public void shouldRaiseErrorWhenUsingAnyRemaining() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.enum2string;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Mapper
|
||||
public interface ErroneousOrderMapperUsingAnyRemaining {
|
||||
|
||||
ErroneousOrderMapperUsingAnyRemaining INSTANCE = Mappers.getMapper( ErroneousOrderMapperUsingAnyRemaining.class );
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping( source = MappingConstants.NULL, target = "DEFAULT" ),
|
||||
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL ),
|
||||
@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "SPECIAL" )
|
||||
})
|
||||
String mapWithRemainingAndNull(OrderType orderType);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.enum2string;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderMapper {
|
||||
|
||||
OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping(source = "EXTRA", target = "SPECIAL"),
|
||||
@ValueMapping(source = "STANDARD", target = "DEFAULT"),
|
||||
@ValueMapping(source = "NORMAL", target = "DEFAULT")
|
||||
})
|
||||
String mapNormal(OrderType orderType);
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping( source = MappingConstants.NULL, target = "DEFAULT" ),
|
||||
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL ),
|
||||
@ValueMapping( source = MappingConstants.ANY_UNMAPPED, target = "SPECIAL" )
|
||||
})
|
||||
String withAnyUnmappedAndNull(OrderType orderType);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.string2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Mapper
|
||||
public interface ErroneousOrderMapperUsingNoAnyRemainingAndNoAnyUnmapped {
|
||||
|
||||
ErroneousOrderMapperUsingNoAnyRemainingAndNoAnyUnmapped INSTANCE =
|
||||
Mappers.getMapper( ErroneousOrderMapperUsingNoAnyRemainingAndNoAnyUnmapped.class );
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping( source = MappingConstants.NULL, target = "STANDARD" ),
|
||||
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL )
|
||||
})
|
||||
OrderType map(String orderType);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.string2enum;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderMapper {
|
||||
|
||||
OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping(source = "SPECIAL", target = "EXTRA" ),
|
||||
@ValueMapping(source = "DEFAULT", target = "STANDARD"),
|
||||
@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "RETAIL" )
|
||||
})
|
||||
OrderType mapNormal(String orderType);
|
||||
|
||||
@ValueMappings({
|
||||
@ValueMapping( source = MappingConstants.NULL, target = "STANDARD" ),
|
||||
@ValueMapping( source = "DEFAULT", target = MappingConstants.NULL ),
|
||||
@ValueMapping( source = MappingConstants.ANY_UNMAPPED, target = "RETAIL" )
|
||||
})
|
||||
OrderType mapWithAnyUnmapped(String orderType);
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.string2enum;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
|
||||
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@IssueKey( "1557" )
|
||||
@WithClasses({ OrderType.class, OrderMapper.class })
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class StringToEnumMappingTest {
|
||||
|
||||
@Test
|
||||
public void testTheNormalStuff() {
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( null ) ).isNull();
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "SPECIAL" ) ).isEqualTo( OrderType.EXTRA );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "DEFAULT" ) ).isEqualTo( OrderType.STANDARD );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "RETAIL" ) ).isEqualTo( OrderType.RETAIL );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "B2B" ) ).isEqualTo( OrderType.B2B );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "STANDARD" ) ).isEqualTo( OrderType.STANDARD );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "NORMAL" ) ).isEqualTo( OrderType.NORMAL );
|
||||
assertThat( OrderMapper.INSTANCE.mapNormal( "blah" ) ).isEqualTo( OrderType.RETAIL );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemainingAndNull() {
|
||||
assertThat( OrderMapper.INSTANCE.mapWithAnyUnmapped( null ) ).isEqualTo( OrderType.STANDARD );
|
||||
assertThat( OrderMapper.INSTANCE.mapWithAnyUnmapped( "DEFAULT" ) ).isNull();
|
||||
assertThat( OrderMapper.INSTANCE.mapWithAnyUnmapped( "BLAH" ) ).isEqualTo( OrderType.RETAIL );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses(ErroneousOrderMapperUsingNoAnyRemainingAndNoAnyUnmapped.class)
|
||||
@ExpectedCompilationOutcome(
|
||||
value = CompilationResult.SUCCEEDED,
|
||||
diagnostics = {
|
||||
@Diagnostic(type = ErroneousOrderMapperUsingNoAnyRemainingAndNoAnyUnmapped.class,
|
||||
kind = javax.tools.Diagnostic.Kind.WARNING,
|
||||
line = 28,
|
||||
messageRegExp = "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" is advisable for mapping of " +
|
||||
"type String to an enum type" )
|
||||
}
|
||||
)
|
||||
public void shouldRaiseErrorWhenUsingAnyRemaining() {
|
||||
}
|
||||
|
||||
}
|
@ -3,9 +3,11 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
@ -3,9 +3,11 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
@ -3,9 +3,11 @@
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.value;
|
||||
package org.mapstruct.ap.test.value.enum2enum;
|
||||
|
||||
import javax.annotation.Generated;
|
||||
import org.mapstruct.ap.test.value.ExternalOrderType;
|
||||
import org.mapstruct.ap.test.value.OrderType;
|
||||
|
||||
@Generated(
|
||||
value = "org.mapstruct.ap.MappingProcessor",
|
Loading…
x
Reference in New Issue
Block a user