#1557 & #1936 String-to-enum and enum-to-String (#1938)

* #1557 making enum-to-string and string-to-enum

* #1936 <ANY_REMAINING> and <ANY_UNMAPPED> not ignored when inverting
This commit is contained in:
Sjaak Derksen 2019-10-07 20:30:20 +02:00 committed by GitHub
parent 44ae27d7ca
commit 507ec1b384
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 572 additions and 153 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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\\." )
}
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {
}
}

View File

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

View File

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

View File

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