mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
Add EnumTransformationStrategy SPI (#2089)
Add a new custom EnumTransformationStrategy SPI which can be used for providing custom way of name based mapping for enums. Add 4 out of the box transformation strategies: * prefix - add a prefix to the name based enum mapping * stripPrefix - remove a prefix from the name based enum mapping * suffix - add a suffix to the name based enum mapping * stripSuffix - remove a suffix from the name based enum mapping This can be achieved by using the new `EnumMapping` e.g. Add suffix `_TYPE` to all enums: `@EnumMapping(nameTransformationStrategy = "suffix", configuration = "_TYPE")` With this it would be possible to achieve what is needed in #796, #1220, #1789.
This commit is contained in:
parent
b5fe96c9da
commit
7b5a54971f
123
core/src/main/java/org/mapstruct/EnumMapping.java
Normal file
123
core/src/main/java/org/mapstruct/EnumMapping.java
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Configured the mapping between two value types.
|
||||
* <p><strong>Example:</strong> Using a suffix for enums</p>
|
||||
* <pre><code class='java'>
|
||||
* public enum CheeseType {
|
||||
* BRIE,
|
||||
* ROQUEFORT
|
||||
* }
|
||||
*
|
||||
* public enum CheeseTypeSuffixed {
|
||||
* BRIE_TYPE,
|
||||
* ROQUEFORT_TYPE
|
||||
* }
|
||||
*
|
||||
* @Mapper
|
||||
* public interface CheeseMapper {
|
||||
*
|
||||
* @EnumMapping(nameTransformationStrategy = "suffix", configuration = "_TYPE")
|
||||
* CheeseTypeSuffixed map(Cheese cheese);
|
||||
*
|
||||
* @InheritInverseConfiguration
|
||||
* Cheese map(CheeseTypeSuffixed cheese);
|
||||
*
|
||||
* }
|
||||
* </code></pre>
|
||||
* <pre><code class='java'>
|
||||
* // generates
|
||||
* public class CheeseMapperImpl implements CheeseMapper {
|
||||
*
|
||||
* @Override
|
||||
* public CheeseTypeSuffixed map(Cheese cheese) {
|
||||
* if ( cheese == null ) {
|
||||
* return null;
|
||||
* }
|
||||
*
|
||||
* CheeseTypeSuffixed cheeseTypeSuffixed;
|
||||
*
|
||||
* switch ( cheese ) {
|
||||
* case BRIE:
|
||||
* cheeseTypeSuffixed = CheeseTypeSuffixed.BRIE_TYPE;
|
||||
* break;
|
||||
* case ROQUEFORT:
|
||||
* cheeseTypeSuffixed = CheeseTypeSuffixed.ROQUEFORT_TYPE;
|
||||
* break;
|
||||
* default:
|
||||
* throw new IllegalArgumentException( "Unexpected enum constant: " + cheese );
|
||||
* }
|
||||
*
|
||||
* return cheeseTypeSuffixed;
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* public Cheese map(CheeseTypeSuffixed cheese) {
|
||||
* if ( cheese == null ) {
|
||||
* return null;
|
||||
* }
|
||||
*
|
||||
* CheeseType cheeseType;
|
||||
*
|
||||
* switch ( cheese ) {
|
||||
* case BRIE_TYPE:
|
||||
* cheeseType = CheeseType.BRIE;
|
||||
* break;
|
||||
* case ROQUEFORT_TYPE:
|
||||
* cheeseType = CheeseType.ROQUEFORT;
|
||||
* break;
|
||||
* default:
|
||||
* throw new IllegalArgumentException( "Unexpected enum constant: " + cheese );
|
||||
* }
|
||||
*
|
||||
* return cheeseType;
|
||||
* }
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
* @since 1.4
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface EnumMapping {
|
||||
|
||||
/**
|
||||
* Specifies the name transformation strategy that should be used for implicit mapping between enums.
|
||||
* Known strategies are:
|
||||
* <ul>
|
||||
* <li>{@link MappingConstants#SUFFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
||||
* suffix to the source enum</li>
|
||||
* <li>{@link MappingConstants#STRIP_SUFFIX_TRANSFORMATION} - strips the the given {@link #configuration()}
|
||||
* from the end of the source enum</li>
|
||||
* <li>{@link MappingConstants#PREFIX_TRANSFORMATION} - applies the given {@link #configuration()} as a
|
||||
* prefix to the source enum</li>
|
||||
* <li>{@link MappingConstants#STRIP_PREFIX_TRANSFORMATION} - strips the given {@link #configuration()} from
|
||||
* the start of the source enum</li>
|
||||
* </ul>
|
||||
*
|
||||
* It is possible to use custom name transformation strategies by implementing the {@code
|
||||
* EnumTransformationStrategy} SPI.
|
||||
*
|
||||
* @return the name transformation strategy
|
||||
*/
|
||||
String nameTransformationStrategy();
|
||||
|
||||
/**
|
||||
* The configuration that should be passed on the appropriate name transformation strategy.
|
||||
* e.g. a suffix that should be applied to the source enum when doing name based mapping.
|
||||
*
|
||||
* @return the configuration to use
|
||||
*/
|
||||
String configuration();
|
||||
}
|
@ -36,4 +36,34 @@ public final class MappingConstants {
|
||||
*/
|
||||
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
|
||||
|
||||
/**
|
||||
* In an {@link EnumMapping} this represent the enum transformation strategy that adds a suffix to the source enum.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public static final String SUFFIX_TRANSFORMATION = "suffix";
|
||||
|
||||
/**
|
||||
* In an {@link EnumMapping} this represent the enum transformation strategy that strips a suffix from the source
|
||||
* enum.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public static final String STRIP_SUFFIX_TRANSFORMATION = "stripSuffix";
|
||||
|
||||
/**
|
||||
* In an {@link EnumMapping} this represent the enum transformation strategy that adds a prefix to the source enum.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public static final String PREFIX_TRANSFORMATION = "prefix";
|
||||
|
||||
/**
|
||||
* In an {@link EnumMapping} this represent the enum transformation strategy that strips a prefix from the source
|
||||
* enum.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public static final String STRIP_PREFIX_TRANSFORMATION = "stripPrefix";
|
||||
|
||||
}
|
||||
|
@ -198,3 +198,19 @@ A nice example is to provide support for a custom builder strategy.
|
||||
include::{processor-ap-main}/spi/NoOpBuilderProvider.java[tag=documentation]
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
[[custom-enum-transformation-strategy]]
|
||||
=== Custom Enum Transformation Strategy
|
||||
|
||||
MapStruct offers the possibility to other transformations strategies by implementing `EnumTransformationStrategy` via the Service Provider Interface (SPI).
|
||||
A nice example is to provide support for a custom transformation strategy.
|
||||
|
||||
.Custom Enum Transformation Strategy which lower-cases the value and applies a suffix
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
include::{processor-ap-test}/value/nametransformation/CustomEnumTransformationStrategy.java[tag=documentation]
|
||||
----
|
||||
====
|
@ -159,3 +159,106 @@ MapStruct supports enum to a String mapping along the same lines as is described
|
||||
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.
|
||||
|
||||
=== Custom name transformation
|
||||
|
||||
When no `@ValueMapping`(s) are defined then each constant from the source enum is mapped to a constant with the same name in the target enum type.
|
||||
However, there are cases where the source enum needs to be transformed before doing the mapping.
|
||||
E.g. a suffix needs to be applied to map from the source into the target enum.
|
||||
|
||||
.Enum types
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
public enum CheeseType {
|
||||
|
||||
BRIE,
|
||||
ROQUEFORT
|
||||
}
|
||||
|
||||
public enum CheeseTypeSuffixed {
|
||||
|
||||
BRIE_TYPE,
|
||||
ROQUEFORT_TYPE
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
.Enum mapping method with custom name transformation strategy
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
@Mapper
|
||||
public interface CheeseMapper {
|
||||
|
||||
CheeseMapper INSTANCE = Mappers.getMapper( CheeseMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = "suffix", configuration = "_TYPE")
|
||||
CheeseTypeSuffixed map(CheeseType cheese);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
CheeseType map(CheeseTypeSuffix cheese);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
.Enum mapping method with custom name transformation strategy result
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
// GENERATED CODE
|
||||
public class CheeseSuffixMapperImpl implements CheeseSuffixMapper {
|
||||
|
||||
@Override
|
||||
public CheeseTypeSuffixed map(CheeseType cheese) {
|
||||
if ( cheese == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CheeseTypeSuffixed cheeseTypeSuffixed;
|
||||
|
||||
switch ( cheese ) {
|
||||
case BRIE: cheeseTypeSuffixed = CheeseTypeSuffixed.BRIE_TYPE;
|
||||
break;
|
||||
case ROQUEFORT: cheeseTypeSuffixed = CheeseTypeSuffixed.ROQUEFORT_TYPE;
|
||||
break;
|
||||
default: throw new IllegalArgumentException( "Unexpected enum constant: " + cheese );
|
||||
}
|
||||
|
||||
return cheeseTypeSuffixed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheeseType map(CheeseTypeSuffixed cheese) {
|
||||
if ( cheese == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CheeseType cheeseType;
|
||||
|
||||
switch ( cheese ) {
|
||||
case BRIE_TYPE: cheeseType = CheeseType.BRIE;
|
||||
break;
|
||||
case ROQUEFORT_TYPE: cheeseType = CheeseType.ROQUEFORT;
|
||||
break;
|
||||
default: throw new IllegalArgumentException( "Unexpected enum constant: " + cheese );
|
||||
}
|
||||
|
||||
return cheeseType;
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
MapStruct provides the following out of the box enum name transformation strategies:
|
||||
|
||||
* _suffix_ - Applies a suffix on the source enum
|
||||
* _stripSuffix_ - Strips a suffix from the source enum
|
||||
* _prefix_ - Applies a prefix on the source enum
|
||||
* _stripPrefix_ - Strips a prefix from the source enum
|
||||
|
||||
It is also possible to register custom strategies.
|
||||
For more information on how to do that have a look at <<custom-enum-transformation-strategy>>
|
||||
|
@ -14,6 +14,7 @@ import org.mapstruct.BeforeMapping;
|
||||
import org.mapstruct.Builder;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.DecoratedWith;
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.InheritConfiguration;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.IterableMapping;
|
||||
@ -43,6 +44,7 @@ import org.mapstruct.tools.gem.GemDefinition;
|
||||
@GemDefinition(Mappings.class)
|
||||
@GemDefinition(IterableMapping.class)
|
||||
@GemDefinition(BeanMapping.class)
|
||||
@GemDefinition(EnumMapping.class)
|
||||
@GemDefinition(MapMapping.class)
|
||||
@GemDefinition(TargetType.class)
|
||||
@GemDefinition(MappingTarget.class)
|
||||
|
@ -20,4 +20,12 @@ public final class MappingConstantsGem {
|
||||
public static final String ANY_REMAINING = "<ANY_REMAINING>";
|
||||
|
||||
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
|
||||
|
||||
public static final String SUFFIX_TRANSFORMATION = "suffix";
|
||||
|
||||
public static final String STRIP_SUFFIX_TRANSFORMATION = "stripSuffix";
|
||||
|
||||
public static final String PREFIX_TRANSFORMATION = "prefix";
|
||||
|
||||
public static final String STRIP_PREFIX_TRANSFORMATION = "stripPrefix";
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
|
||||
forgedMappingMethod = new ValueMappingMethod.Builder()
|
||||
.method( forgedMethod )
|
||||
.valueMappings( forgedMethod.getOptions().getValueMappings() )
|
||||
.enumMapping( forgedMethod.getOptions().getEnumMappingOptions() )
|
||||
.mappingContext( ctx )
|
||||
.build();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Services;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
import org.mapstruct.ap.spi.MappingExclusionProvider;
|
||||
|
||||
/**
|
||||
@ -104,6 +105,7 @@ public class MappingBuilderContext {
|
||||
private final Types typeUtils;
|
||||
private final FormattingMessager messager;
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
private final Map<String, EnumTransformationStrategy> enumTransformationStrategies;
|
||||
private final Options options;
|
||||
private final TypeElement mapperTypeElement;
|
||||
private final List<SourceMethod> sourceModel;
|
||||
@ -113,11 +115,13 @@ public class MappingBuilderContext {
|
||||
private final Map<ForgedMethod, ForgedMethod> forgedMethodsUnderCreation =
|
||||
new HashMap<>();
|
||||
|
||||
//CHECKSTYLE:OFF
|
||||
public MappingBuilderContext(TypeFactory typeFactory,
|
||||
Elements elementUtils,
|
||||
Types typeUtils,
|
||||
FormattingMessager messager,
|
||||
AccessorNamingUtils accessorNaming,
|
||||
Map<String, EnumTransformationStrategy> enumTransformationStrategies,
|
||||
Options options,
|
||||
MappingResolver mappingResolver,
|
||||
TypeElement mapper,
|
||||
@ -128,12 +132,14 @@ public class MappingBuilderContext {
|
||||
this.typeUtils = typeUtils;
|
||||
this.messager = messager;
|
||||
this.accessorNaming = accessorNaming;
|
||||
this.enumTransformationStrategies = enumTransformationStrategies;
|
||||
this.options = options;
|
||||
this.mappingResolver = mappingResolver;
|
||||
this.mapperTypeElement = mapper;
|
||||
this.sourceModel = sourceModel;
|
||||
this.mapperReferences = mapperReferences;
|
||||
}
|
||||
//CHECKSTYLE:ON
|
||||
|
||||
/**
|
||||
* Returns a map which is used to track which forged methods are under creation.
|
||||
@ -180,6 +186,10 @@ public class MappingBuilderContext {
|
||||
return accessorNaming;
|
||||
}
|
||||
|
||||
public Map<String, EnumTransformationStrategy> getEnumTransformationStrategies() {
|
||||
return enumTransformationStrategies;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
@ -7,19 +7,23 @@ package org.mapstruct.ap.internal.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.source.EnumMappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.ValueMappingOptions;
|
||||
import org.mapstruct.ap.internal.gem.BeanMappingGem;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
import static org.mapstruct.ap.internal.gem.MappingConstantsGem.ANY_REMAINING;
|
||||
import static org.mapstruct.ap.internal.gem.MappingConstantsGem.ANY_UNMAPPED;
|
||||
@ -45,6 +49,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
private Method method;
|
||||
private MappingBuilderContext ctx;
|
||||
private ValueMappings valueMappings;
|
||||
private EnumMappingOptions enumMapping;
|
||||
private EnumTransformationStrategyInvoker enumTransformationInvoker;
|
||||
|
||||
public Builder mappingContext(MappingBuilderContext mappingContext) {
|
||||
this.ctx = mappingContext;
|
||||
@ -61,7 +67,18 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueMappingMethod build( ) {
|
||||
public Builder enumMapping(EnumMappingOptions enumMapping) {
|
||||
this.enumMapping = enumMapping;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueMappingMethod build() {
|
||||
|
||||
if ( !enumMapping.isValid() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
initializeEnumTransformationStrategy();
|
||||
|
||||
// initialize all relevant parameters
|
||||
List<MappingEntry> mappingEntries = new ArrayList<>();
|
||||
@ -99,6 +116,23 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
);
|
||||
}
|
||||
|
||||
private void initializeEnumTransformationStrategy() {
|
||||
if ( !enumMapping.hasAnnotation() ) {
|
||||
enumTransformationInvoker = EnumTransformationStrategyInvoker.DEFAULT;
|
||||
}
|
||||
else {
|
||||
Map<String, EnumTransformationStrategy> enumTransformationStrategies =
|
||||
ctx.getEnumTransformationStrategies();
|
||||
|
||||
String nameTransformationStrategy = enumMapping.getNameTransformationStrategy();
|
||||
if ( enumTransformationStrategies.containsKey( nameTransformationStrategy ) ) {
|
||||
enumTransformationInvoker = new EnumTransformationStrategyInvoker( enumTransformationStrategies.get(
|
||||
nameTransformationStrategy ), enumMapping.getNameTransformationConfiguration() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<MappingEntry> enumToEnumMapping(Method method, Type sourceType, Type targetType ) {
|
||||
|
||||
List<MappingEntry> mappings = new ArrayList<>();
|
||||
@ -120,11 +154,36 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
// add mappings based on name
|
||||
if ( !valueMappings.hasMapAnyUnmapped ) {
|
||||
|
||||
// get all target constants
|
||||
List<String> targetConstants = method.getReturnType().getEnumConstants();
|
||||
// We store the target constants in a map in order to support inherited inverse mapping
|
||||
// When using a nameTransformationStrategy the transformation should be done on the target enum
|
||||
// instead of the source enum
|
||||
Map<String, String> targetConstants = new LinkedHashMap<>();
|
||||
|
||||
boolean enumMappingInverse = enumMapping.isInverse();
|
||||
for ( String targetEnumConstant : method.getReturnType().getEnumConstants() ) {
|
||||
if ( enumMappingInverse ) {
|
||||
// If the mapping is inverse we have to change the target enum constant
|
||||
targetConstants.put(
|
||||
enumTransformationInvoker.transform( targetEnumConstant ),
|
||||
targetEnumConstant
|
||||
);
|
||||
}
|
||||
else {
|
||||
targetConstants.put( targetEnumConstant, targetEnumConstant );
|
||||
}
|
||||
}
|
||||
|
||||
for ( String sourceConstant : new ArrayList<>( unmappedSourceConstants ) ) {
|
||||
if ( targetConstants.contains( sourceConstant ) ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
|
||||
String targetConstant;
|
||||
if ( !enumMappingInverse ) {
|
||||
targetConstant = enumTransformationInvoker.transform( sourceConstant );
|
||||
}
|
||||
else {
|
||||
targetConstant = sourceConstant;
|
||||
}
|
||||
|
||||
if ( targetConstants.containsKey( targetConstant ) ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, targetConstants.get( targetConstant ) ) );
|
||||
unmappedSourceConstants.remove( sourceConstant );
|
||||
}
|
||||
}
|
||||
@ -175,7 +234,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
|
||||
// all remaining constants are mapped
|
||||
for ( String sourceConstant : unmappedSourceConstants ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
|
||||
String targetConstant = enumTransformationInvoker.transform( sourceConstant );
|
||||
mappings.add( new MappingEntry( sourceConstant, targetConstant ) );
|
||||
}
|
||||
}
|
||||
return mappings;
|
||||
@ -204,7 +264,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
|
||||
// all remaining constants are mapped
|
||||
for ( String sourceConstant : unmappedSourceConstants ) {
|
||||
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
|
||||
String stringConstant = enumTransformationInvoker.transform( sourceConstant );
|
||||
mappings.add( new MappingEntry( stringConstant, sourceConstant ) );
|
||||
}
|
||||
}
|
||||
return mappings;
|
||||
@ -229,7 +290,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
for ( ValueMappingOptions mappedConstant : valueMappings.regularValueMappings ) {
|
||||
|
||||
if ( !sourceEnumConstants.contains( mappedConstant.getSource() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
mappedConstant.getMirror(),
|
||||
mappedConstant.getSourceAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
@ -279,7 +341,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
for ( ValueMappingOptions mappedConstant : valueMappings.regularValueMappings ) {
|
||||
if ( !NULL.equals( mappedConstant.getTarget() )
|
||||
&& !targetEnumConstants.contains( mappedConstant.getTarget() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
mappedConstant.getMirror(),
|
||||
mappedConstant.getTargetAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
@ -292,7 +355,8 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
|
||||
if ( valueMappings.defaultTarget != null && !NULL.equals( valueMappings.defaultTarget.getTarget() )
|
||||
&& !targetEnumConstants.contains( valueMappings.defaultTarget.getTarget() ) ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
valueMappings.defaultTarget.getMirror(),
|
||||
valueMappings.defaultTarget.getTargetAnnotationValue(),
|
||||
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
|
||||
@ -318,6 +382,31 @@ public class ValueMappingMethod extends MappingMethod {
|
||||
}
|
||||
}
|
||||
|
||||
private static class EnumTransformationStrategyInvoker {
|
||||
|
||||
private static final EnumTransformationStrategyInvoker DEFAULT = new EnumTransformationStrategyInvoker(
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
private final EnumTransformationStrategy transformationStrategy;
|
||||
private final String configuration;
|
||||
|
||||
private EnumTransformationStrategyInvoker(
|
||||
EnumTransformationStrategy transformationStrategy, String configuration) {
|
||||
this.transformationStrategy = transformationStrategy;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
private String transform(String source) {
|
||||
if ( transformationStrategy == null ) {
|
||||
return source;
|
||||
}
|
||||
|
||||
return transformationStrategy.transform( source, configuration );
|
||||
}
|
||||
}
|
||||
|
||||
private static class ValueMappings {
|
||||
|
||||
List<ValueMappingOptions> regularValueMappings = new ArrayList<>();
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.internal.model.source;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
|
||||
import org.mapstruct.ap.internal.gem.EnumMappingGem;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Strings;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Message.ENUMMAPPING_INCORRECT_TRANSFORMATION_STRATEGY;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class EnumMappingOptions extends DelegatingOptions {
|
||||
|
||||
private final EnumMappingGem enumMapping;
|
||||
private final boolean inverse;
|
||||
private final boolean valid;
|
||||
|
||||
private EnumMappingOptions(EnumMappingGem enumMapping, boolean inverse, boolean valid, DelegatingOptions next) {
|
||||
super( next );
|
||||
this.enumMapping = enumMapping;
|
||||
this.inverse = inverse;
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAnnotation() {
|
||||
return enumMapping != null;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public String getNameTransformationStrategy() {
|
||||
return enumMapping.nameTransformationStrategy().get();
|
||||
}
|
||||
|
||||
public String getNameTransformationConfiguration() {
|
||||
return enumMapping.configuration().get();
|
||||
}
|
||||
|
||||
public boolean isInverse() {
|
||||
return inverse;
|
||||
}
|
||||
|
||||
public EnumMappingOptions inverse() {
|
||||
return new EnumMappingOptions( enumMapping, true, valid, next() );
|
||||
}
|
||||
|
||||
public static EnumMappingOptions getInstanceOn(ExecutableElement method, MapperOptions mapperOptions,
|
||||
Map<String, EnumTransformationStrategy> enumTransformationStrategies, FormattingMessager messager) {
|
||||
|
||||
EnumMappingGem enumMapping = EnumMappingGem.instanceOn( method );
|
||||
if ( enumMapping == null ) {
|
||||
return new EnumMappingOptions( null, false, true, mapperOptions );
|
||||
}
|
||||
else if ( !isConsistent( enumMapping, method, enumTransformationStrategies, messager ) ) {
|
||||
return new EnumMappingOptions( null, false, false, mapperOptions );
|
||||
}
|
||||
|
||||
return new EnumMappingOptions(
|
||||
enumMapping,
|
||||
false,
|
||||
true,
|
||||
mapperOptions
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isConsistent(EnumMappingGem gem, ExecutableElement method,
|
||||
Map<String, EnumTransformationStrategy> enumTransformationStrategies, FormattingMessager messager) {
|
||||
|
||||
String strategy = gem.nameTransformationStrategy().getValue();
|
||||
|
||||
if ( !enumTransformationStrategies.containsKey( strategy ) ) {
|
||||
String registeredStrategies = Strings.join( enumTransformationStrategies.keySet(), ", " );
|
||||
messager.printMessage(
|
||||
method,
|
||||
gem.mirror(),
|
||||
gem.nameTransformationStrategy().getAnnotationValue(),
|
||||
ENUMMAPPING_INCORRECT_TRANSFORMATION_STRATEGY,
|
||||
strategy,
|
||||
registeredStrategies
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ public class MappingMethodOptions {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
@ -39,18 +40,21 @@ public class MappingMethodOptions {
|
||||
private IterableMappingOptions iterableMapping;
|
||||
private MapMappingOptions mapMapping;
|
||||
private BeanMappingOptions beanMapping;
|
||||
private EnumMappingOptions enumMappingOptions;
|
||||
private List<ValueMappingOptions> valueMappings;
|
||||
private boolean fullyInitialized;
|
||||
|
||||
public MappingMethodOptions(MapperOptions mapper, Set<MappingOptions> mappings,
|
||||
IterableMappingOptions iterableMapping,
|
||||
MapMappingOptions mapMapping, BeanMappingOptions beanMapping,
|
||||
EnumMappingOptions enumMappingOptions,
|
||||
List<ValueMappingOptions> valueMappings) {
|
||||
this.mapper = mapper;
|
||||
this.mappings = mappings;
|
||||
this.iterableMapping = iterableMapping;
|
||||
this.mapMapping = mapMapping;
|
||||
this.beanMapping = beanMapping;
|
||||
this.enumMappingOptions = enumMappingOptions;
|
||||
this.valueMappings = valueMappings;
|
||||
}
|
||||
|
||||
@ -83,6 +87,10 @@ public class MappingMethodOptions {
|
||||
return beanMapping;
|
||||
}
|
||||
|
||||
public EnumMappingOptions getEnumMappingOptions() {
|
||||
return enumMappingOptions;
|
||||
}
|
||||
|
||||
public List<ValueMappingOptions> getValueMappings() {
|
||||
return valueMappings;
|
||||
}
|
||||
@ -99,6 +107,10 @@ public class MappingMethodOptions {
|
||||
this.beanMapping = beanMapping;
|
||||
}
|
||||
|
||||
public void setEnumMappingOptions(EnumMappingOptions enumMappingOptions) {
|
||||
this.enumMappingOptions = enumMappingOptions;
|
||||
}
|
||||
|
||||
public void setValueMappings(List<ValueMappingOptions> valueMappings) {
|
||||
this.valueMappings = valueMappings;
|
||||
}
|
||||
@ -141,6 +153,17 @@ public class MappingMethodOptions {
|
||||
setBeanMapping( BeanMappingOptions.forInheritance( templateOptions.getBeanMapping( ) ) );
|
||||
}
|
||||
|
||||
if ( !getEnumMappingOptions().hasAnnotation() && templateOptions.getEnumMappingOptions().hasAnnotation() ) {
|
||||
EnumMappingOptions newEnumMappingOptions;
|
||||
if ( isInverse ) {
|
||||
newEnumMappingOptions = templateOptions.getEnumMappingOptions().inverse();
|
||||
}
|
||||
else {
|
||||
newEnumMappingOptions = templateOptions.getEnumMappingOptions();
|
||||
}
|
||||
setEnumMappingOptions( newEnumMappingOptions );
|
||||
}
|
||||
|
||||
if ( getValueMappings() == null ) {
|
||||
if ( templateOptions.getValueMappings() != null ) {
|
||||
// there were no mappings, so the inherited mappings are the new ones
|
||||
|
@ -84,6 +84,7 @@ public class SourceMethod implements Method {
|
||||
private MapperOptions mapper = null;
|
||||
private List<SourceMethod> prototypeMethods = Collections.emptyList();
|
||||
private List<ValueMappingOptions> valueMappings;
|
||||
private EnumMappingOptions enumMappingOptions;
|
||||
private ParameterProvidedMethods contextProvidedMethods;
|
||||
|
||||
public Builder setDeclaringMapper(Type declaringMapper) {
|
||||
@ -136,6 +137,11 @@ public class SourceMethod implements Method {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setEnumMappingOptions(EnumMappingOptions enumMappingOptions) {
|
||||
this.enumMappingOptions = enumMappingOptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setTypeUtils(Types typeUtils) {
|
||||
this.typeUtils = typeUtils;
|
||||
return this;
|
||||
@ -172,8 +178,15 @@ public class SourceMethod implements Method {
|
||||
mappings = Collections.emptySet();
|
||||
}
|
||||
|
||||
MappingMethodOptions mappingMethodOptions =
|
||||
new MappingMethodOptions( mapper, mappings, iterableMapping, mapMapping, beanMapping, valueMappings );
|
||||
MappingMethodOptions mappingMethodOptions = new MappingMethodOptions(
|
||||
mapper,
|
||||
mappings,
|
||||
iterableMapping,
|
||||
mapMapping,
|
||||
beanMapping,
|
||||
enumMappingOptions,
|
||||
valueMappings
|
||||
);
|
||||
|
||||
return new SourceMethod( this, mappingMethodOptions );
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.internal.util.RoundContext;
|
||||
import org.mapstruct.ap.internal.util.workarounds.TypesDecorator;
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
/**
|
||||
* Default implementation of the processor context.
|
||||
@ -41,6 +42,7 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
private final VersionInformation versionInformation;
|
||||
private final Types delegatingTypes;
|
||||
private final AccessorNamingUtils accessorNaming;
|
||||
private final RoundContext roundContext;
|
||||
|
||||
public DefaultModelElementProcessorContext(ProcessingEnvironment processingEnvironment, Options options,
|
||||
RoundContext roundContext, Map<String, String> notToBeImported) {
|
||||
@ -50,6 +52,7 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
this.accessorNaming = roundContext.getAnnotationProcessorContext().getAccessorNaming();
|
||||
this.versionInformation = DefaultVersionInformation.fromProcessingEnvironment( processingEnvironment );
|
||||
this.delegatingTypes = new TypesDecorator( processingEnvironment, versionInformation );
|
||||
this.roundContext = roundContext;
|
||||
this.typeFactory = new TypeFactory(
|
||||
processingEnvironment.getElementUtils(),
|
||||
delegatingTypes,
|
||||
@ -90,6 +93,11 @@ public class DefaultModelElementProcessorContext implements ProcessorContext {
|
||||
return accessorNaming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, EnumTransformationStrategy> getEnumTransformationStrategies() {
|
||||
return roundContext.getAnnotationProcessorContext().getEnumTransformationStrategies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
|
@ -101,6 +101,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
typeUtils,
|
||||
messager,
|
||||
accessorNaming,
|
||||
context.getEnumTransformationStrategies(),
|
||||
options,
|
||||
new MappingResolverImpl(
|
||||
messager,
|
||||
@ -336,9 +337,13 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
|
||||
.mappingContext( mappingContext )
|
||||
.method( method )
|
||||
.valueMappings( mappingOptions.getValueMappings() )
|
||||
.enumMapping( mappingOptions.getEnumMappingOptions() )
|
||||
.build();
|
||||
|
||||
if ( valueMappingMethod != null ) {
|
||||
mappingMethods.add( valueMappingMethod );
|
||||
}
|
||||
}
|
||||
else if ( method.isRemovedEnumMapping() ) {
|
||||
messager.printMessage(
|
||||
method.getExecutable(),
|
||||
|
@ -10,6 +10,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
@ -27,6 +28,7 @@ import org.mapstruct.ap.internal.model.common.Parameter;
|
||||
import org.mapstruct.ap.internal.model.common.Type;
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.model.source.BeanMappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.EnumMappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.IterableMappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.MapMappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.MapperOptions;
|
||||
@ -47,6 +49,7 @@ import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||
import org.mapstruct.ap.internal.util.Executables;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
import static org.mapstruct.ap.internal.util.Executables.getAllEnclosedExecutableElements;
|
||||
|
||||
@ -68,6 +71,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
private FormattingMessager messager;
|
||||
private TypeFactory typeFactory;
|
||||
private AccessorNamingUtils accessorNaming;
|
||||
private Map<String, EnumTransformationStrategy> enumTransformationStrategies;
|
||||
private Types typeUtils;
|
||||
private Elements elementUtils;
|
||||
|
||||
@ -78,6 +82,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
this.accessorNaming = context.getAccessorNaming();
|
||||
this.typeUtils = context.getTypeUtils();
|
||||
this.elementUtils = context.getElementUtils();
|
||||
this.enumTransformationStrategies = context.getEnumTransformationStrategies();
|
||||
|
||||
this.messager.note( 0, Message.PROCESSING_NOTE, mapperTypeElement );
|
||||
|
||||
@ -273,6 +278,13 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
typeUtils
|
||||
);
|
||||
|
||||
EnumMappingOptions enumMappingOptions = EnumMappingOptions.getInstanceOn(
|
||||
method,
|
||||
mapperOptions,
|
||||
enumTransformationStrategies,
|
||||
messager
|
||||
);
|
||||
|
||||
return new SourceMethod.Builder()
|
||||
.setExecutable( method )
|
||||
.setParameters( parameters )
|
||||
@ -284,6 +296,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
.setIterableMappingOptions( iterableMappingOptions )
|
||||
.setMapMappingOptions( mapMappingOptions )
|
||||
.setValueMappingOptionss( getValueMappings( method ) )
|
||||
.setEnumMappingOptions( enumMappingOptions )
|
||||
.setTypeUtils( typeUtils )
|
||||
.setTypeFactory( typeFactory )
|
||||
.setPrototypeMethods( prototypeMethods )
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mapstruct.ap.internal.processor;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.annotation.processing.Filer;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
@ -16,6 +17,7 @@ import org.mapstruct.ap.internal.option.Options;
|
||||
import org.mapstruct.ap.internal.util.AccessorNamingUtils;
|
||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||
import org.mapstruct.ap.internal.version.VersionInformation;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
/**
|
||||
* A processor which performs one task of the mapper generation, e.g. retrieving
|
||||
@ -51,6 +53,8 @@ public interface ModelElementProcessor<P, R> {
|
||||
|
||||
AccessorNamingUtils getAccessorNaming();
|
||||
|
||||
Map<String, EnumTransformationStrategy> getEnumTransformationStrategies();
|
||||
|
||||
Options getOptions();
|
||||
|
||||
VersionInformation getVersionInformation();
|
||||
|
@ -9,7 +9,9 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import javax.annotation.processing.Messager;
|
||||
@ -22,6 +24,7 @@ import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||
import org.mapstruct.ap.spi.BuilderProvider;
|
||||
import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.DefaultBuilderProvider;
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
import org.mapstruct.ap.spi.FreeBuilderAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.ImmutablesBuilderProvider;
|
||||
@ -39,6 +42,7 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
||||
private BuilderProvider builderProvider;
|
||||
private AccessorNamingStrategy accessorNamingStrategy;
|
||||
private boolean initialized;
|
||||
private Map<String, EnumTransformationStrategy> enumTransformationStrategies;
|
||||
|
||||
private AccessorNamingUtils accessorNaming;
|
||||
private Elements elementUtils;
|
||||
@ -105,6 +109,28 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
||||
);
|
||||
}
|
||||
this.accessorNaming = new AccessorNamingUtils( this.accessorNamingStrategy );
|
||||
|
||||
|
||||
this.enumTransformationStrategies = new LinkedHashMap<>();
|
||||
ServiceLoader<EnumTransformationStrategy> transformationStrategiesLoader = ServiceLoader.load(
|
||||
EnumTransformationStrategy.class,
|
||||
AnnotationProcessorContext.class.getClassLoader()
|
||||
);
|
||||
|
||||
for ( EnumTransformationStrategy transformationStrategy : transformationStrategiesLoader ) {
|
||||
String transformationStrategyName = transformationStrategy.getStrategyName();
|
||||
if ( enumTransformationStrategies.containsKey( transformationStrategyName ) ) {
|
||||
throw new IllegalStateException(
|
||||
"Multiple EnumTransformationStrategies are using the same ma,e. Found: " +
|
||||
enumTransformationStrategies.get( transformationStrategyName ) + " and " +
|
||||
transformationStrategy + " for name " + transformationStrategyName );
|
||||
}
|
||||
|
||||
transformationStrategy.init( this );
|
||||
enumTransformationStrategies.put( transformationStrategyName, transformationStrategy );
|
||||
}
|
||||
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
@ -216,4 +242,9 @@ public class AnnotationProcessorContext implements MapStructProcessingEnvironmen
|
||||
initialize();
|
||||
return builderProvider;
|
||||
}
|
||||
|
||||
public Map<String, EnumTransformationStrategy> getEnumTransformationStrategies() {
|
||||
initialize();
|
||||
return enumTransformationStrategies;
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ public enum Message {
|
||||
ENUMMAPPING_UNDEFINED_TARGET( "A target constant must be specified for mappings of an enum mapping method." ),
|
||||
ENUMMAPPING_UNMAPPED_SOURCES( "The following constants from the source enum have no corresponding constant in the target enum and must be be mapped via adding additional mappings: %s." ),
|
||||
ENUMMAPPING_REMOVED( "Mapping of Enums via @Mapping is removed. Please use @ValueMapping instead!" ),
|
||||
ENUMMAPPING_INCORRECT_TRANSFORMATION_STRATEGY( "There is no registered EnumTransformationStrategy for '%s'. Registered strategies are: %s." ),
|
||||
|
||||
LIFECYCLEMETHOD_AMBIGUOUS_PARAMETERS( "Lifecycle method has multiple matching parameters (e. g. same type), in this case please ensure to name the parameters in the lifecycle and mapping method identical. This lifecycle method will not be used for the mapping method '%s'.", Diagnostic.Kind.WARNING),
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
import org.mapstruct.util.Experimental;
|
||||
|
||||
/**
|
||||
* A service provider interface for transforming name based value mappings.
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
* @since 1.4
|
||||
*/
|
||||
@Experimental("This SPI can have it's signature changed in subsequent releases")
|
||||
public interface EnumTransformationStrategy {
|
||||
|
||||
/**
|
||||
* Initializes the enum transformation strategy with the MapStruct processing environment.
|
||||
*
|
||||
* @param processingEnvironment environment for facilities
|
||||
*/
|
||||
default void init(MapStructProcessingEnvironment processingEnvironment) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the strategy.
|
||||
*
|
||||
* @return the name of the strategy, never {@code null}
|
||||
*/
|
||||
String getStrategyName();
|
||||
|
||||
/**
|
||||
* Transform the given value by using the given {@code configuration}.
|
||||
*
|
||||
* @param value the value that should be transformed
|
||||
* @param configuration the configuration that should be used for the transformation
|
||||
*
|
||||
* @return the transformed value after applying the configuration
|
||||
*/
|
||||
String transform(String value, String configuration);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class PrefixEnumTransformationStrategy implements EnumTransformationStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "prefix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String value, String configuration) {
|
||||
return configuration + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class StripPrefixEnumTransformationStrategy implements EnumTransformationStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "stripPrefix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String value, String configuration) {
|
||||
if ( value.startsWith( configuration ) ) {
|
||||
return value.substring( configuration.length() );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class StripSuffixEnumTransformationStrategy implements EnumTransformationStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "stripSuffix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String value, String configuration) {
|
||||
if ( value.endsWith( configuration ) ) {
|
||||
return value.substring( 0, value.length() - configuration.length() );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class SuffixEnumTransformationStrategy implements EnumTransformationStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "suffix";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String value, String configuration) {
|
||||
return value + configuration;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
# Copyright MapStruct Authors.
|
||||
#
|
||||
# Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
org.mapstruct.ap.spi.PrefixEnumTransformationStrategy
|
||||
org.mapstruct.ap.spi.StripPrefixEnumTransformationStrategy
|
||||
org.mapstruct.ap.spi.StripSuffixEnumTransformationStrategy
|
||||
org.mapstruct.ap.spi.SuffixEnumTransformationStrategy
|
@ -23,5 +23,11 @@ public class ConstantTest {
|
||||
assertThat( MappingConstants.ANY_REMAINING ).isEqualTo( MappingConstantsGem.ANY_REMAINING );
|
||||
assertThat( MappingConstants.ANY_UNMAPPED ).isEqualTo( MappingConstantsGem.ANY_UNMAPPED );
|
||||
assertThat( MappingConstants.NULL ).isEqualTo( MappingConstantsGem.NULL );
|
||||
assertThat( MappingConstants.SUFFIX_TRANSFORMATION ).isEqualTo( MappingConstantsGem.SUFFIX_TRANSFORMATION );
|
||||
assertThat( MappingConstants.STRIP_SUFFIX_TRANSFORMATION )
|
||||
.isEqualTo( MappingConstantsGem.STRIP_SUFFIX_TRANSFORMATION );
|
||||
assertThat( MappingConstants.PREFIX_TRANSFORMATION ).isEqualTo( MappingConstantsGem.PREFIX_TRANSFORMATION );
|
||||
assertThat( MappingConstants.STRIP_PREFIX_TRANSFORMATION )
|
||||
.isEqualTo( MappingConstantsGem.STRIP_PREFIX_TRANSFORMATION );
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.mapstruct.ap.test.value.enum2string;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
@ -27,6 +28,7 @@ public interface OrderMapper {
|
||||
})
|
||||
String mapNormal(OrderType orderType);
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = "prefix", configuration = "PREFIX_")
|
||||
@ValueMappings({
|
||||
@ValueMapping( source = MappingConstants.NULL, target = "DEFAULT" ),
|
||||
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL ),
|
||||
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface CheeseEnumToStringPrefixMapper {
|
||||
|
||||
CheeseEnumToStringPrefixMapper INSTANCE = Mappers.getMapper( CheeseEnumToStringPrefixMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "SWISS_")
|
||||
String map(CheeseType cheese);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "FRENCH_")
|
||||
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = MappingConstants.NULL)
|
||||
CheeseType map(String cheese);
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION, configuration = "SWISS_")
|
||||
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = MappingConstants.NULL)
|
||||
CheeseTypePrefixed mapStripPrefix(String cheese);
|
||||
}
|
@ -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.nametransformation;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface CheeseEnumToStringSuffixMapper {
|
||||
|
||||
CheeseEnumToStringSuffixMapper INSTANCE = Mappers.getMapper( CheeseEnumToStringSuffixMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION, configuration = "_CHEESE_TYPE")
|
||||
String map(CheeseType cheese);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = MappingConstants.NULL)
|
||||
CheeseType map(String cheese);
|
||||
|
||||
@EnumMapping(
|
||||
nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION,
|
||||
configuration = "_CHEESE_TYPE"
|
||||
)
|
||||
@ValueMapping(source = MappingConstants.ANY_REMAINING, target = MappingConstants.NULL)
|
||||
CheeseTypeSuffixed mapStripSuffix(String cheese);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface CheesePrefixMapper {
|
||||
|
||||
CheesePrefixMapper INSTANCE = Mappers.getMapper( CheesePrefixMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.PREFIX_TRANSFORMATION, configuration = "SWISS_")
|
||||
CheeseTypePrefixed map(CheeseType cheese);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
@ValueMapping(source = "DEFAULT", target = MappingConstants.NULL)
|
||||
CheeseType mapInheritInverse(CheeseTypePrefixed cheese);
|
||||
|
||||
@ValueMapping(source = "DEFAULT", target = MappingConstants.NULL)
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_PREFIX_TRANSFORMATION, configuration = "SWISS_")
|
||||
CheeseType mapStripPrefix(CheeseTypePrefixed cheese);
|
||||
}
|
@ -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.nametransformation;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingConstants;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface CheeseSuffixMapper {
|
||||
|
||||
CheeseSuffixMapper INSTANCE = Mappers.getMapper( CheeseSuffixMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = MappingConstants.SUFFIX_TRANSFORMATION, configuration = "_CHEESE_TYPE")
|
||||
CheeseTypeSuffixed map(CheeseType cheese);
|
||||
|
||||
@InheritInverseConfiguration
|
||||
@ValueMapping(source = "DEFAULT", target = MappingConstants.NULL)
|
||||
CheeseType mapInheritInverse(CheeseTypeSuffixed cheese);
|
||||
|
||||
@EnumMapping(
|
||||
nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION,
|
||||
configuration = "_CHEESE_TYPE"
|
||||
)
|
||||
@ValueMapping(source = "DEFAULT", target = MappingConstants.NULL)
|
||||
CheeseType mapStripSuffix(CheeseTypeSuffixed cheese);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public enum CheeseType {
|
||||
|
||||
BRIE,
|
||||
ROQUEFORT
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public enum CheeseTypeCustomSuffix {
|
||||
|
||||
brie_TYPE,
|
||||
roquefort_TYPE,
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public enum CheeseTypePrefixed {
|
||||
|
||||
DEFAULT,
|
||||
SWISS_BRIE,
|
||||
SWISS_ROQUEFORT,
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public enum CheeseTypeSuffixed {
|
||||
|
||||
DEFAULT,
|
||||
BRIE_CHEESE_TYPE,
|
||||
ROQUEFORT_CHEESE_TYPE,
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
// tag::documentation[]
|
||||
|
||||
import org.mapstruct.ap.spi.EnumTransformationStrategy;
|
||||
|
||||
// end::documentation[]
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
// tag::documentation[]
|
||||
public class CustomEnumTransformationStrategy implements EnumTransformationStrategy {
|
||||
|
||||
@Override
|
||||
public String getStrategyName() {
|
||||
return "custom";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String transform(String value, String configuration) {
|
||||
return value.toLowerCase() + configuration;
|
||||
}
|
||||
}
|
||||
// end::documentation[]
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.WithServiceImplementation;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
@WithClasses({
|
||||
CheeseType.class,
|
||||
CheeseTypeSuffixed.class,
|
||||
CheeseTypePrefixed.class,
|
||||
CheeseTypeCustomSuffix.class,
|
||||
})
|
||||
public class EnumNameTransformationStrategyTest {
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
CheeseSuffixMapper.class
|
||||
})
|
||||
public void shouldApplySuffixAndStripSuffixOnEnumToEnumMapping() {
|
||||
CheeseSuffixMapper mapper = CheeseSuffixMapper.INSTANCE;
|
||||
|
||||
assertThat( mapper.map( CheeseType.BRIE ) )
|
||||
.isEqualTo( CheeseTypeSuffixed.BRIE_CHEESE_TYPE );
|
||||
assertThat( mapper.mapInheritInverse( CheeseTypeSuffixed.BRIE_CHEESE_TYPE ) )
|
||||
.isEqualTo( CheeseType.BRIE );
|
||||
assertThat( mapper.mapStripSuffix( CheeseTypeSuffixed.BRIE_CHEESE_TYPE ) )
|
||||
.isEqualTo( CheeseType.BRIE );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
CheesePrefixMapper.class
|
||||
})
|
||||
public void shouldApplyPrefixAndStripPrefixOnEnumToEnumMapping() {
|
||||
CheesePrefixMapper mapper = CheesePrefixMapper.INSTANCE;
|
||||
|
||||
assertThat( mapper.map( CheeseType.BRIE ) )
|
||||
.isEqualTo( CheeseTypePrefixed.SWISS_BRIE );
|
||||
assertThat( mapper.mapInheritInverse( CheeseTypePrefixed.SWISS_BRIE ) )
|
||||
.isEqualTo( CheeseType.BRIE );
|
||||
assertThat( mapper.mapStripPrefix( CheeseTypePrefixed.SWISS_BRIE ) )
|
||||
.isEqualTo( CheeseType.BRIE );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
CheeseEnumToStringSuffixMapper.class
|
||||
})
|
||||
public void shouldApplySuffixAndStripSuffixOnEnumToStringMapping() {
|
||||
CheeseEnumToStringSuffixMapper mapper = CheeseEnumToStringSuffixMapper.INSTANCE;
|
||||
|
||||
assertThat( mapper.map( CheeseType.BRIE ) ).isEqualTo( "BRIE_CHEESE_TYPE" );
|
||||
assertThat( mapper.map( "BRIE_CHEESE_TYPE" ) ).isEqualTo( CheeseType.BRIE );
|
||||
assertThat( mapper.mapStripSuffix( "BRIE" ) ).isEqualTo( CheeseTypeSuffixed.BRIE_CHEESE_TYPE );
|
||||
assertThat( mapper.mapStripSuffix( "DEFAULT" ) ).isEqualTo( CheeseTypeSuffixed.DEFAULT );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
CheeseEnumToStringPrefixMapper.class
|
||||
})
|
||||
public void shouldApplyPrefixAndStripPrefixOnEnumToStringMapping() {
|
||||
CheeseEnumToStringPrefixMapper mapper = CheeseEnumToStringPrefixMapper.INSTANCE;
|
||||
|
||||
assertThat( mapper.map( CheeseType.BRIE ) ).isEqualTo( "SWISS_BRIE" );
|
||||
assertThat( mapper.map( "FRENCH_BRIE" ) ).isEqualTo( CheeseType.BRIE );
|
||||
assertThat( mapper.mapStripPrefix( "BRIE" ) ).isEqualTo( CheeseTypePrefixed.SWISS_BRIE );
|
||||
assertThat( mapper.mapStripPrefix( "DEFAULT" ) ).isEqualTo( CheeseTypePrefixed.DEFAULT );
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
ErroneousNameTransformStrategyMapper.class
|
||||
})
|
||||
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
|
||||
diagnostics = {
|
||||
@Diagnostic(
|
||||
type = ErroneousNameTransformStrategyMapper.class,
|
||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||
line = 20,
|
||||
message = "There is no registered EnumTransformationStrategy for 'custom'. Registered strategies are:" +
|
||||
" prefix, stripPrefix, stripSuffix, suffix."
|
||||
)
|
||||
}
|
||||
)
|
||||
public void shouldGiveCompileErrorWhenUsingUnknownNameTransformStrategy() {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithClasses({
|
||||
ErroneousNameTransformStrategyMapper.class
|
||||
})
|
||||
@WithServiceImplementation(CustomEnumTransformationStrategy.class)
|
||||
public void shouldUseCustomEnumTransformationStrategy() {
|
||||
assertThat( ErroneousNameTransformStrategyMapper.INSTANCE.map( CheeseType.BRIE ) )
|
||||
.isEqualTo( CheeseTypeCustomSuffix.brie_TYPE );
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.nametransformation;
|
||||
|
||||
import org.mapstruct.EnumMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface ErroneousNameTransformStrategyMapper {
|
||||
|
||||
ErroneousNameTransformStrategyMapper INSTANCE = Mappers.getMapper( ErroneousNameTransformStrategyMapper.class );
|
||||
|
||||
@EnumMapping(nameTransformationStrategy = "custom", configuration = "_TYPE")
|
||||
CheeseTypeCustomSuffix map(CheeseType cheese);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user