#749 Introduction of @ValueMapping, @ValueMappings

This commit is contained in:
sjaakd 2016-02-16 22:37:23 +01:00
parent 9b2145c6a8
commit ae4d0f77e1
33 changed files with 1929 additions and 20 deletions

View File

@ -0,0 +1,46 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct;
/**
* Contains all constants defined in the mapping process.
*
* @author Sjaak Derksen
*/
public final class MappingConstants {
private MappingConstants() {
}
/**
* Represents a {@code null} source or target.
*/
public static final String NULL = "<NULL>";
/**
* Represents any source that is not already mapped by either a defined mapping or by means of name based mapping.
*/
public static final String ANY_REMAINING = "<ANY_REMAINING>";
/**
* Represents any source that is not already mapped by a defined mapping.
*/
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
}

View File

@ -37,6 +37,10 @@ import java.util.Date;
* In addition, the attributes {@link #dateFormat()} and {@link #qualifiedBy()} may be used to further define the
* mapping.
*
* <p>
* <b>IMPORTANT NOTE:</b> the enum mapping capability is deprecated and replaced by {@link ValueMapping} it
* will be removed in subsequent versions.
*
* @author Gunnar Morling
*/
@Repeatable(Mappings.class)

View File

@ -0,0 +1,123 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Configures the mapping of source constant value to target constant value.
* <p>
* Supported mappings are
* <ol>
* <li>Enumeration to Enumeration</li>
* </ol>
* <p>
* <B>Example 1:</B>
* <pre>
* <code>
* public enum OrderType { RETAIL, B2B, EXTRA, STANDARD, NORMAL }
*
* public enum ExternalOrderType { RETAIL, B2B, SPECIAL, DEFAULT }
*
* &#64;ValueMapping(source = "EXTRA", target = "SPECIAL"),
* &#64;ValueMapping(source = "STANDARD", target = "DEFAULT"),
* &#64;ValueMapping(source = "NORMAL", target = "DEFAULT")
* ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
* </code>
* Mapping result:
*
* OrderType ExternalOrderType
*
* null null
* OrderType.EXTRA ExternalOrderType.SPECIAL
* OrderType.STANDARD ExternalOrderType.DEFAULT
* OrderType.NORMAL ExternalOrderType.DEFAULT
* OrderType.RETAIL ExternalOrderType.RETAIL
* OrderType.B2B ExternalOrderType.B2B
*
* </pre>
* MapStruct will <B>WARN</B> on incomplete mappings. However, if for some reason no match is found an
* {@link java.lang.IllegalStateException} will be thrown.
* <p>
* <B>Example 2:</B>
* <pre>
* <code>
* &#64;ValueMapping( source = "&lt;NULL&gt;", target = "DEFAULT" ),
* &#64;ValueMapping( source = "STANDARD", target = "&lt;NULL&gt;" ),
* &#64;ValueMapping( source = "&lt;ANY_REMAINING&gt;", target = "SPECIAL" )
* ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
* </code>
* Mapping result:
*
* OrderType ExternalOrderType
*
* null ExternalOrderType.DEFAULT
* OrderType.STANDARD null
* OrderType.RETAIL ExternalOrderType.RETAIL
* OrderType.B2B ExternalOrderType.B2B
* OrderType.NORMAL ExternalOrderType.SPECIAL
* OrderType.EXTRA ExternalOrderType.SPECIAL
*
* </pre>
*
* @author Sjaak Derksen
*/
@Repeatable(ValueMappings.class)
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface ValueMapping {
/**
* The source value constant to use for this mapping.
*
* <p>
* <b>Valid values:</b>
* <ol>
* <li>enum constant name</li>
* <li>{@link MappingConstants#NULL}</li>
* <li>{@link MappingConstants#ANY_REMAINING}</li>
* <li>{@link MappingConstants#ANY_UNMAPPED}</li>
* </ol>
* <p>
* <b>NOTE:</b>When using &lt;ANY_REMAINING&gt;, MapStruct will perform the normal name based mapping, in which
* source is mapped to target based on enum identifier equality. Using &lt;ANY_UNMAPPED&gt; will not apply name
* based mapping.
*
* @return The source value.
*/
String source();
/**
* The target value constant to use for this mapping.
*
* <p>
* <b>Valid values:</b>
* <ol>
* <li>enum constant name</li>
* <li>{@link MappingConstants#NULL}</li>
* </ol>
*
* @return The target value.
*/
String target();
}

View File

@ -0,0 +1,37 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Constructs a set of value (constant) mappings.
*
* @author Sjaak Derksen
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ValueMappings {
ValueMapping[] value();
}

View File

@ -36,6 +36,10 @@ import java.util.Date;
* In addition, the attributes {@link #dateFormat()} and {@link #qualifiedBy()} may be used to further define the
* mapping.
*
* <p>
* <b>IMPORTANT NOTE:</b> the enum mapping capability is deprecated and replaced by {@link ValueMapping} it
* will be removed in subsequent versions.
*
* @author Gunnar Morling
*/
@Retention(RetentionPolicy.CLASS)

View File

@ -0,0 +1,126 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Configures the mapping of source constant value to target constant value.
* <p>
* Supported mappings are
* <ol>
* <li>Enumeration to Enumeration</li>
* </ol>
* <p>
* <B>Example 1:</B>
* <pre>
* <code>
* public enum OrderType { RETAIL, B2B, EXTRA, STANDARD, NORMAL }
*
* public enum ExternalOrderType { RETAIL, B2B, SPECIAL, DEFAULT }
*
* &#64;ValueMappings({
* &#64;ValueMapping(source = "EXTRA", target = "SPECIAL"),
* &#64;ValueMapping(source = "STANDARD", target = "DEFAULT"),
* &#64;ValueMapping(source = "NORMAL", target = "DEFAULT")
* })
* ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
* </code>
* Mapping result:
*
* OrderType ExternalOrderType
*
* null null
* OrderType.EXTRA ExternalOrderType.SPECIAL
* OrderType.STANDARD ExternalOrderType.DEFAULT
* OrderType.NORMAL ExternalOrderType.DEFAULT
* OrderType.RETAIL ExternalOrderType.RETAIL
* OrderType.B2B ExternalOrderType.B2B
*
* </pre>
* MapStruct will <B>WARN</B> on incomplete mappings. However, if for some reason no match is found an
* {@link java.lang.IllegalStateException} will be thrown.
* <p>
* <B>Example 2:</B>
* <pre>
* <code>
* &#64;ValueMappings({
* &#64;ValueMapping( source = "&lt;NULL&gt;", target = "DEFAULT" ),
* &#64;ValueMapping( source = "STANDARD", target = "&lt;NULL&gt;" ),
* &#64;ValueMapping( source = "&lt;ANY_REMAINING&gt;", target = "SPECIAL" )
* })
* ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
* </code>
* Mapping result:
*
* OrderType ExternalOrderType
*
* null ExternalOrderType.DEFAULT
* OrderType.STANDARD null
* OrderType.RETAIL ExternalOrderType.RETAIL
* OrderType.B2B ExternalOrderType.B2B
* OrderType.NORMAL ExternalOrderType.SPECIAL
* OrderType.EXTRA ExternalOrderType.SPECIAL
*
* </pre>
*
* @author Sjaak Derksen
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface ValueMapping {
/**
* The source value constant to use for this mapping.
*
* <p>
* <b>Valid values:</b>
* <ol>
* <li>enum constant name</li>
* <li>{@link MappingConstants#NULL}</li>
* <li>{@link MappingConstants#ANY_REMAINING}</li>
* <li>{@link MappingConstants#ANY_UNMAPPED}</li>
* </ol>
* <p>
* <b>NOTE:</b>When using &lt;ANY_REMAINING&gt;, MapStruct will perform the normal name based mapping, in which
* source is mapped to target based on enum identifier equality. Using &lt;ANY_UNMAPPED&gt; will not apply name
* based mapping.
*
* @return The source value.
*/
String source();
/**
* The target value constant to use for this mapping.
*
* <p>
* <b>Valid values:</b>
* <ol>
* <li>enum constant name</li>
* <li>{@link MappingConstants#NULL}</li>
* </ol>
*
* @return The target value.
*/
String target();
}

View File

@ -0,0 +1,37 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Constructs a set of value (constant) mappings.
*
* @author Sjaak Derksen
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface ValueMappings {
ValueMapping[] value();
}

View File

@ -1095,11 +1095,13 @@ When an iterable or map mapping method declares an interface type as return type
|===
[[mapping-enum-types]]
== Mapping enum types
== Mapping Values
=== Mapping enum types
MapStruct supports the generation of methods which map one Java enum type into another.
By default, each constant from the source enum is mapped to a constant with the same name in the target enum type. If required, a constant from the source enum may be mapped to a constant with another name with help of the `@Mapping` annotation. Several constants from the source enum can be mapped to the same constant in the target type.
By default, each constant from the source enum is mapped to a constant with the same name in the target enum type. If required, a constant from the source enum may be mapped to a constant with another name with help of the `@ValueMapping` annotation. Several constants from the source enum can be mapped to the same constant in the target type.
The following shows an example:
@ -1113,17 +1115,129 @@ public interface OrderMapper {
OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
@Mappings({
@Mapping(source = "EXTRA", target = "SPECIAL"),
@Mapping(source = "STANDARD", target = "DEFAULT"),
@Mapping(source = "NORMAL", target = "DEFAULT")
@ValueMappings({
@ValueMapping(source = "EXTRA", target = "SPECIAL"),
@ValueMapping(source = "STANDARD", target = "DEFAULT"),
@ValueMapping(source = "NORMAL", target = "DEFAULT")
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}
----
====
Note that 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 `@Mapping`. This ensures that all constants are mapped in a safe and predictable manner.
.Enum mapping method result
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
// GENERATED CODE
public class OrderMapperImpl implements OrderMapper {
@Override
public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {
if ( orderType == null ) {
return null;
}
ExternalOrderType externalOrderType_;
switch ( orderType ) {
case EXTRA: externalOrderType_ = ExternalOrderType.SPECIAL;
break;
case STANDARD: externalOrderType_ = ExternalOrderType.DEFAULT;
break;
case NORMAL: externalOrderType_ = ExternalOrderType.DEFAULT;
break;
case RETAIL: externalOrderType_ = ExternalOrderType.RETAIL;
break;
case B2B: externalOrderType_ = ExternalOrderType.B2B;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + orderType );
}
return externalOrderType_;
}
}
----
====
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_UNMATCHED>`.
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.
MapStruct will *not* attempt such name based mapping for `<ANY_UNMATCHED>` and directly apply the target specified in the `@ValueMapping` with `<ANY_UNMATCHED>` source to the remainder.
MapStruct is able to handle `null` sources and `null` targets by means of the `<NULL>` keyword.
[TIP]
====
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`.
.Enum mapping method, <NULL> and <ANY_REMAINING>
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
@Mapper
public interface SpecialOrderMapper {
SpecialOrderMapper INSTANCE = Mappers.getMapper( SpecialOrderMapper.class );
@ValueMappings({
@ValueMapping( source = MappingConstants.NULL, target = "DEFAULT" ),
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL ),
@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "SPECIAL" )
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}
----
====
.Enum mapping method result, <NULL> and <ANY_REMAINING>
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
// GENERATED CODE
public class SpecialOrderMapperImpl implements SpecialOrderMapper {
@Override
public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {
if ( orderType == null ) {
return ExternalOrderType.DEFAULT;
}
ExternalOrderType externalOrderType_;
switch ( orderType ) {
case STANDARD: externalOrderType_ = null;
break;
case RETAIL: externalOrderType_ = ExternalOrderType.RETAIL;
break;
case B2B: externalOrderType_ = ExternalOrderType.B2B;
break;
default: externalOrderType_ = ExternalOrderType.SPECIAL;
}
return externalOrderType_;
}
}
----
====
*Note:* MapStruct would have refrained from mapping the `RETAIL` and `B2B` when `<ANY_UNMAPPED>` was used instead of `<ANY_REMAINING>`.
[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.
====
[[object-factories]]
== Object factories

View File

@ -90,7 +90,7 @@ public class EnumMappingMethod extends MappingMethod {
targetConstants.add( mapping.getTargetName() );
}
ctx.getMessager().printMessage( method.getExecutable(),
Message.ENUMMAPPING_MULTIPLE_TARGETS,
Message.ENUMMAPPING_MULTIPLE_SOURCES,
enumConstant,
Strings.join( targetConstants, ", " )
);
@ -183,7 +183,7 @@ public class EnumMappingMethod extends MappingMethod {
if ( !unmappedSourceEnumConstants.isEmpty() ) {
ctx.getMessager().printMessage( method.getExecutable(),
Message.ENUMMAPPING_UNMAPPED_TARGETS,
Message.ENUMMAPPING_UNMAPPED_SOURCES,
Strings.join( unmappedSourceEnumConstants, ", " )
);
}

View File

@ -0,0 +1,289 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.model;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.type.TypeMirror;
import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.model.source.ValueMapping;
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
import org.mapstruct.ap.internal.prism.MappingConstantsPrism;
import static org.mapstruct.ap.internal.util.Collections.first;
import org.mapstruct.ap.internal.util.Message;
import org.mapstruct.ap.internal.util.Strings;
/**
* A {@link ValueMappingMethod} which maps one value type to another, optionally configured by one or more
* {@link ValueMapping}s. For now, only enum-to-enum mapping is supported.
*
* @author Sjaak Derksen
*/
public class ValueMappingMethod extends MappingMethod {
private final List<MappingEntry> valueMappings;
private final String defaultTarget;
private final String nullTarget;
private final boolean throwIllegalArgumentException;
public static class Builder {
private SourceMethod method;
private MappingBuilderContext ctx;
private final List<ValueMapping> trueValueMappings = new ArrayList<ValueMapping>();
private ValueMapping defaultTargetValue = null;
private ValueMapping nullTargetValue = null;
private boolean applyNamebasedMappings = true;
public Builder mappingContext(MappingBuilderContext mappingContext) {
this.ctx = mappingContext;
return this;
}
public Builder souceMethod(SourceMethod sourceMethod) {
this.method = sourceMethod;
return this;
}
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 );
}
}
return this;
}
public ValueMappingMethod build( ) {
// initialize all relevant parameters
List<MappingEntry> mappingEntries = new ArrayList<MappingEntry>();
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 ) {
defaultTarget = defaultTargetValue.getTarget();
}
else {
throwIllegalArgumentException = true;
}
}
// do before / after lifecycle mappings
SelectionParameters selectionParameters = getSelectionParameters( method );
List<LifecycleCallbackMethodReference> beforeMappingMethods
= LifecycleCallbackFactory.beforeMappingMethods( method, selectionParameters, ctx );
List<LifecycleCallbackMethodReference> afterMappingMethods
= LifecycleCallbackFactory.afterMappingMethods( method, selectionParameters, ctx );
// finallyn return a mapping
return new ValueMappingMethod( method, mappingEntries, nullTarget, defaultTarget,
throwIllegalArgumentException, beforeMappingMethods, afterMappingMethods );
}
private List<MappingEntry> enumToEnumMapping(SourceMethod method) {
List<MappingEntry> mappings = new ArrayList<MappingEntry>();
List<String> unmappedSourceConstants
= new ArrayList<String>( first( method.getSourceParameters() ).getType().getEnumConstants() );
if ( !reportErrorIfMappedEnumConstantsDontExist( method ) ) {
return mappings;
}
// Start to fill the mappings with the defined valuemappings
for ( ValueMapping valueMapping : trueValueMappings ) {
String target =
MappingConstantsPrism.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 ) {
// get all target constants
List<String> targetConstants = method.getReturnType().getEnumConstants();
for ( String sourceConstant : new ArrayList<String>( unmappedSourceConstants ) ) {
if ( targetConstants.contains( sourceConstant ) ) {
mappings.add( new MappingEntry( sourceConstant, sourceConstant ) );
unmappedSourceConstants.remove( sourceConstant );
}
}
if ( defaultTargetValue == null && !unmappedSourceConstants.isEmpty() ) {
// 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,
Strings.join( unmappedSourceConstants, ", " )
);
}
}
return mappings;
}
private SelectionParameters getSelectionParameters(SourceMethod method) {
BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() );
if ( beanMappingPrism != null ) {
List<TypeMirror> qualifiers = beanMappingPrism.qualifiedBy();
List<String> qualifyingNames = beanMappingPrism.qualifiedByName();
TypeMirror resultType = beanMappingPrism.resultType();
return new SelectionParameters( qualifiers, qualifyingNames, resultType );
}
return null;
}
private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) {
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
boolean foundIncorrectMapping = false;
for ( ValueMapping mappedConstant : trueValueMappings ) {
if ( !sourceEnumConstants.contains( mappedConstant.getSource() ) ) {
ctx.getMessager().printMessage( method.getExecutable(),
mappedConstant.getMirror(),
mappedConstant.getSourceAnnotationValue(),
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
mappedConstant.getSource(),
first( method.getSourceParameters() ).getType()
);
foundIncorrectMapping = true;
}
if ( !MappingConstantsPrism.NULL.equals( mappedConstant.getTarget() )
&& !targetEnumConstants.contains( mappedConstant.getTarget() ) ) {
ctx.getMessager().printMessage( method.getExecutable(),
mappedConstant.getMirror(),
mappedConstant.getTargetAnnotationValue(),
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
mappedConstant.getTarget(),
method.getReturnType()
);
foundIncorrectMapping = true;
}
}
if ( defaultTargetValue != null && !MappingConstantsPrism.NULL.equals( defaultTargetValue.getTarget() )
&& !targetEnumConstants.contains( defaultTargetValue.getTarget() ) ) {
ctx.getMessager().printMessage( method.getExecutable(),
defaultTargetValue.getMirror(),
defaultTargetValue.getTargetAnnotationValue(),
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
defaultTargetValue.getTarget(),
method.getReturnType()
);
foundIncorrectMapping = true;
}
if ( nullTargetValue != null && MappingConstantsPrism.NULL.equals( nullTargetValue.getTarget() )
&& !targetEnumConstants.contains( nullTargetValue.getTarget() ) ) {
ctx.getMessager().printMessage( method.getExecutable(),
nullTargetValue.getMirror(),
nullTargetValue.getTargetAnnotationValue(),
Message.VALUEMAPPING_NON_EXISTING_CONSTANT,
nullTargetValue.getTarget(),
method.getReturnType()
);
foundIncorrectMapping = true;
}
return !foundIncorrectMapping;
}
}
private ValueMappingMethod(Method method, List<MappingEntry> enumMappings, String nullTarget, String defaultTarget,
boolean throwIllegalArgumentException, List<LifecycleCallbackMethodReference> beforeMappingMethods,
List<LifecycleCallbackMethodReference> afterMappingMethods) {
super( method, beforeMappingMethods, afterMappingMethods );
this.valueMappings = enumMappings;
this.nullTarget = nullTarget;
this.defaultTarget = defaultTarget;
this.throwIllegalArgumentException = throwIllegalArgumentException;
}
public List<MappingEntry> getValueMappings() {
return valueMappings;
}
public String getDefaultTarget() {
return defaultTarget;
}
public String getNullTarget() {
return nullTarget;
}
public boolean isThrowIllegalArgumentException() {
return throwIllegalArgumentException;
}
public Parameter getSourceParameter() {
return first( getParameters() );
}
public static class MappingEntry {
private final String source;
private final String target;
MappingEntry( String source, String target ) {
this.source = source;
this.target = target;
}
public String getSource() {
return source;
}
public String getTarget() {
return target;
}
}
}

View File

@ -19,6 +19,7 @@
package org.mapstruct.ap.internal.model.source;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -36,14 +37,16 @@ public class MappingOptions {
private IterableMapping iterableMapping;
private MapMapping mapMapping;
private BeanMapping beanMapping;
private List<ValueMapping> valueMappings;
private boolean fullyInitialized;
public MappingOptions(Map<String, List<Mapping>> mappings, IterableMapping iterableMapping, MapMapping mapMapping,
BeanMapping beanMapping) {
BeanMapping beanMapping, List<ValueMapping> valueMappings ) {
this.mappings = mappings;
this.iterableMapping = iterableMapping;
this.mapMapping = mapMapping;
this.beanMapping = beanMapping;
this.valueMappings = valueMappings;
}
/**
@ -66,6 +69,10 @@ public class MappingOptions {
return beanMapping;
}
public List<ValueMapping> getValueMappings() {
return valueMappings;
}
public void setMappings(Map<String, List<Mapping>> mappings) {
this.mappings = mappings;
}
@ -82,6 +89,10 @@ public class MappingOptions {
this.beanMapping = beanMapping;
}
public void setValueMappings(List<ValueMapping> valueMappings) {
this.valueMappings = valueMappings;
}
/**
* @return the {@code true}, iff the options have been fully initialized by applying all available inheritance
* options
@ -124,6 +135,29 @@ public class MappingOptions {
}
}
if ( getValueMappings() == null ) {
if ( inherited.getValueMappings() != null ) {
// there were no mappings, so the inherited mappings are the new ones
setValueMappings( inherited.getValueMappings() );
}
else {
setValueMappings( Collections.<ValueMapping>emptyList() );
}
}
else {
if ( inherited.getValueMappings() != null ) {
// iff there are also inherited mappings, we reverse and add them.
for ( ValueMapping inheritedValueMapping : inherited.getValueMappings() ) {
ValueMapping valueMapping = isInverse ? inheritedValueMapping.reverse() : inheritedValueMapping;
if ( valueMapping != null
&& !getValueMappings().contains( valueMapping ) ) {
getValueMappings().add( valueMapping );
}
}
}
}
Map<String, List<Mapping>> newMappings = new HashMap<String, List<Mapping>>();
for ( List<Mapping> lmappings : inherited.getMappings().values() ) {

View File

@ -91,6 +91,7 @@ public class SourceMethod implements Method {
private FormattingMessager messager = null;
private MapperConfiguration mapperConfig = null;
private List<SourceMethod> prototypeMethods = Collections.emptyList();
private List<ValueMapping> valueMappings;
public Builder() {
}
@ -140,6 +141,11 @@ public class SourceMethod implements Method {
return this;
}
public Builder setValueMappings(List<ValueMapping> valueMappings) {
this.valueMappings = valueMappings;
return this;
}
public Builder setTypeUtils(Types typeUtils) {
this.typeUtils = typeUtils;
return this;
@ -173,7 +179,7 @@ public class SourceMethod implements Method {
public SourceMethod build() {
MappingOptions mappingOptions
= new MappingOptions( mappings, iterableMapping, mapMapping, beanMapping );
= new MappingOptions( mappings, iterableMapping, mapMapping, beanMapping, valueMappings );
SourceMethod sourceMethod = new SourceMethod(
@ -199,6 +205,8 @@ public class SourceMethod implements Method {
}
return sourceMethod;
}
}
@SuppressWarnings("checkstyle:parameternumber")
@ -374,6 +382,16 @@ public class SourceMethod implements Method {
&& getResultType().isEnumType();
}
/**
* The default enum mapping (no mappings specified) will from now on be handled as a value mapping. If there
* are any @Mapping / @Mappings defined on the method, then the deprecated enum behavior should be executed.
*
* @return whether (true) or not (false) to execute value mappings
*/
public boolean isValueMapping() {
return isEnumMapping() && mappingOptions.getMappings().isEmpty();
}
private boolean equals(Object o1, Object o2) {
return (o1 == null && o2 == null) || (o1 != null) && o1.equals( o2 );
}
@ -554,4 +572,5 @@ public class SourceMethod implements Method {
public boolean isUpdateMethod() {
return getMappingTargetParameter() != null;
}
}

View File

@ -0,0 +1,164 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.model.source;
import java.util.List;
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;
/**
* Represents the mapping between one value constant and another.
*
* @author Sjaak Derksen
*/
public class ValueMapping {
private final String source;
private final String target;
private final AnnotationMirror mirror;
private final AnnotationValue sourceAnnotationValue;
private final AnnotationValue targetAnnotationValue;
public static void fromMappingsPrism(ValueMappingsPrism mappingsAnnotation, ExecutableElement method,
FormattingMessager messager, List<ValueMapping> mappings) {
boolean anyFound = false;
for ( ValueMappingPrism mappingPrism : mappingsAnnotation.value() ) {
ValueMapping mapping = fromMappingPrism( mappingPrism, method, messager );
if ( mapping != null ) {
if ( !mappings.contains( mapping ) ) {
mappings.add( mapping );
}
else {
messager.printMessage(
method,
mappingPrism.mirror,
mappingPrism.values.target(),
Message.VALUEMAPPING_DUPLICATE_SOURCE,
mappingPrism.source()
);
}
if ( MappingConstantsPrism.ANY_REMAINING.equals( mapping.source )
|| MappingConstantsPrism.ANY_UNMAPPED.equals( mapping.source ) ) {
if ( anyFound ) {
messager.printMessage(
method,
mappingPrism.mirror,
mappingPrism.values.target(),
Message.VALUEMAPPING_ANY_AREADY_DEFINED,
mappingPrism.source()
);
}
anyFound = true;
}
}
}
}
public static ValueMapping fromMappingPrism(ValueMappingPrism mappingPrism, ExecutableElement element,
FormattingMessager messager) {
return new ValueMapping( mappingPrism.source(), mappingPrism.target(), mappingPrism.mirror,
mappingPrism.values.source(), mappingPrism.values.target() );
}
private ValueMapping(String source, String target, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue,
AnnotationValue targetAnnotationValue ) {
this.source = source;
this.target = target;
this.mirror = mirror;
this.sourceAnnotationValue = sourceAnnotationValue;
this.targetAnnotationValue = targetAnnotationValue;
}
/**
* @return the name of the constant in the source.
*/
public String getSource() {
return source;
}
/**
* @return the name of the constant in the target.
*/
public String getTarget() {
return target;
}
public AnnotationMirror getMirror() {
return mirror;
}
public AnnotationValue getSourceAnnotationValue() {
return sourceAnnotationValue;
}
public AnnotationValue getTargetAnnotationValue() {
return targetAnnotationValue;
}
public ValueMapping reverse() {
ValueMapping result;
if ( !MappingConstantsPrism.ANY_REMAINING.equals( source )
|| !MappingConstantsPrism.ANY_UNMAPPED.equals( source ) ) {
result = new ValueMapping(
target,
source,
mirror,
sourceAnnotationValue,
targetAnnotationValue );
}
else {
result = null;
}
return result;
}
@Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + (this.source != null ? this.source.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
final ValueMapping other = (ValueMapping) obj;
if ( (this.source == null) ? (other.source != null) : !this.source.equals( other.source ) ) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,37 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.prism;
/**
* Prism for the enum {@link org.mapstruct.MappingConstants}
*
* @author Sjaak Derksen
*/
public final class MappingConstantsPrism {
private MappingConstantsPrism() {
}
public static final String NULL = "<NULL>";
public static final String ANY_REMAINING = "<ANY_REMAINING>";
public static final String ANY_UNMAPPED = "<ANY_UNMAPPED>";
}

View File

@ -35,6 +35,8 @@ import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.Qualifier;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.TargetType;
import net.java.dev.hickory.prism.GeneratePrism;
@ -63,6 +65,8 @@ import org.mapstruct.Named;
@GeneratePrism(value = Named.class, publicAccess = true),
@GeneratePrism(value = AfterMapping.class, publicAccess = true),
@GeneratePrism(value = BeforeMapping.class, publicAccess = true),
@GeneratePrism(value = ValueMapping.class, publicAccess = true),
@GeneratePrism(value = ValueMappings.class, publicAccess = true),
// external types
@GeneratePrism(value = XmlElementDecl.class, publicAccess = true),

View File

@ -47,6 +47,7 @@ import org.mapstruct.ap.internal.model.Mapper;
import org.mapstruct.ap.internal.model.MapperReference;
import org.mapstruct.ap.internal.model.MappingBuilderContext;
import org.mapstruct.ap.internal.model.MappingMethod;
import org.mapstruct.ap.internal.model.ValueMappingMethod;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.model.source.MappingOptions;
@ -320,8 +321,21 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
hasFactoryMethod = mapMappingMethod.getFactoryMethod() != null;
mappingMethods.add( mapMappingMethod );
}
else if ( method.isValueMapping() ) {
// prefer value mappings over enum mapping
ValueMappingMethod valueMappingMethod = new ValueMappingMethod.Builder()
.mappingContext( mappingContext )
.souceMethod( method )
.valueMappings( mappingOptions.getValueMappings() )
.build();
mappingMethods.add( valueMappingMethod );
}
else if ( method.isEnumMapping() ) {
messager.printMessage(
method.getExecutable(),
Message.ENUMMAPPING_DEPRECATED );
EnumMappingMethod.Builder builder = new EnumMappingMethod.Builder();
MappingMethod enumMappingMethod = builder
.mappingContext( mappingContext )

View File

@ -43,11 +43,14 @@ import org.mapstruct.ap.internal.model.source.IterableMapping;
import org.mapstruct.ap.internal.model.source.MapMapping;
import org.mapstruct.ap.internal.model.source.Mapping;
import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.model.source.ValueMapping;
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
import org.mapstruct.ap.internal.prism.IterableMappingPrism;
import org.mapstruct.ap.internal.prism.MapMappingPrism;
import org.mapstruct.ap.internal.prism.MappingPrism;
import org.mapstruct.ap.internal.prism.MappingsPrism;
import org.mapstruct.ap.internal.prism.ValueMappingPrism;
import org.mapstruct.ap.internal.prism.ValueMappingsPrism;
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
import org.mapstruct.ap.internal.util.Executables;
import org.mapstruct.ap.internal.util.FormattingMessager;
@ -245,6 +248,7 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
.setBeanMapping(
BeanMapping.fromPrism( BeanMappingPrism.getInstanceOn( method ), method, messager )
)
.setValueMappings( getValueMappings( method ) )
.setTypeUtils( typeUtils )
.setMessager( messager )
.setTypeFactory( typeFactory )
@ -481,4 +485,32 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
return mappings;
}
/**
* Retrieves the mappings configured via {@code @ValueMapping} from the given
* method.
*
* @param method The method of interest
*
* @return The mappings for the given method, keyed by target property name
*/
private List<ValueMapping> getValueMappings(ExecutableElement method) {
List<ValueMapping> valueMappings = new ArrayList<ValueMapping>();
ValueMappingPrism mappingAnnotation = ValueMappingPrism.getInstanceOn( method );
ValueMappingsPrism mappingsAnnotation = ValueMappingsPrism.getInstanceOn( method );
if ( mappingAnnotation != null ) {
ValueMapping valueMapping = ValueMapping.fromMappingPrism( mappingAnnotation, method, messager );
if ( valueMapping != null ) {
valueMappings.add( valueMapping );
}
}
if ( mappingsAnnotation != null ) {
ValueMapping.fromMappingsPrism( mappingsAnnotation, method, messager, valueMappings );
}
return valueMappings;
}
}

View File

@ -63,11 +63,12 @@ public enum Message {
ITERABLEMAPPING_MAPPING_NOT_FOUND( "No implementation can be generated for this method. Found no method nor implicit conversion for mapping source element type into target element type." ),
ITERABLEMAPPING_NO_ELEMENTS( "'nullValueMappingStrategy','dateformat', 'qualifiedBy' and 'elementTargetType' are undefined in @IterableMapping, define at least one of them." ),
ENUMMAPPING_MULTIPLE_TARGETS( "One enum constant must not be mapped to more than one target constant, but constant %s is mapped to %s." ),
ENUMMAPPING_MULTIPLE_SOURCES( "One enum constant must not be mapped to more than one target constant, but constant %s is mapped to %s." ),
ENUMMAPPING_UNDEFINED_SOURCE( "A source constant must be specified for mappings of an enum mapping method." ),
ENUMMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s." ),
ENUMMAPPING_UNDEFINED_TARGET( "A target constant must be specified for mappings of an enum mapping method." ),
ENUMMAPPING_UNMAPPED_TARGETS( "The following constants from the source enum have no corresponding constant in the target enum and must be be mapped via @Mapping: %s." ),
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_DEPRECATED( "Mapping of Enums via @Mapping is going to be removed in future versions of MapStruct. Please use @ValueMapping instead!", Diagnostic.Kind.WARNING ),
DECORATOR_NO_SUBTYPE( "Specified decorator type is no subtype of the annotated mapper type." ),
DECORATOR_CONSTRUCTOR( "Specified decorator type has no default constructor nor a constructor with a single parameter accepting the decorated mapper type." ),
@ -95,8 +96,6 @@ public enum Message {
RETRIEVAL_WILDCARD_SUPER_BOUND_SOURCE( "Can't generate mapping method for a wildcard super bound source." ),
RETRIEVAL_WILDCARD_EXTENDS_BOUND_RESULT( "Can't generate mapping method for a wildcard extends bound result." ),
INHERITCONFIGURATION_BOTH( "Method cannot be annotated with both a @InheritConfiguration and @InheritInverseConfiguration." ),
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
INHERITINVERSECONFIGURATION_INVALID_NAME( "None of the candidates %s() matches given name: \"%s\"." ),
@ -107,7 +106,13 @@ public enum Message {
INHERITCONFIGURATION_DUPLICATE_MATCHES( "Given name \"%s\" matches several candidate methods: %s." ),
INHERITCONFIGURATION_NO_NAME_MATCH( "Given name \"%s\" does not match the only candidate. Did you mean: \"%s\"." ),
INHERITCONFIGURATION_MULTIPLE_PROTOTYPE_METHODS_MATCH( "More than one configuration prototype method is applicable. Use @InheritConfiguration to select one of them explicitly: %s." ),
INHERITCONFIGURATION_CYCLE( "Cycle detected while evaluating inherited configurations. Inheritance path: %s" );
INHERITCONFIGURATION_CYCLE( "Cycle detected while evaluating inherited configurations. Inheritance path: %s" ),
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 source enum have no corresponding constant in the target enum and must be be mapped via adding additional mappings: %s." ),
VALUEMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s." );
// CHECKSTYLE:ON
private final String description;

View File

@ -0,0 +1,56 @@
<#--
Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
and/or other contributors as indicated by the @authors tag. See the
copyright.txt file in the distribution for a full listing of all
contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
@Override
public <@includeModel object=returnType/> ${name}(<@includeModel object=sourceParameter/>) {
<#list beforeMappingReferencesWithoutMappingTarget as callback>
<@includeModel object=callback targetBeanName=resultName targetType=resultType/>
<#if !callback_has_next>
</#if>
</#list>
if ( ${sourceParameter.name} == null ) {
return <#if nullTarget??><@includeModel object=returnType/>.${nullTarget}<#else>null</#if>;
}
<@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>;
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>;
}
<#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

@ -37,11 +37,22 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
* @author Gunnar Morling
*/
@IssueKey("128")
@WithClasses({ OrderMapper.class, OrderEntity.class, OrderType.class, OrderDto.class, ExternalOrderType.class })
@WithClasses({ OrderEntity.class, OrderType.class, OrderDto.class, ExternalOrderType.class })
@RunWith(AnnotationProcessorTestRunner.class)
public class EnumMappingTest {
@Test
@WithClasses( OrderMapper.class )
@ExpectedCompilationOutcome(
value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = OrderMapper.class,
kind = Kind.WARNING,
line = 41,
messageRegExp = "Mapping of Enums via @Mapping is going to be removed in future versions of "
+ "MapStruct\\. Please use @ValueMapping instead!")
}
)
public void shouldGenerateEnumMappingMethod() {
ExternalOrderType target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.B2B );
assertThat( target ).isEqualTo( ExternalOrderType.B2B );
@ -51,6 +62,17 @@ public class EnumMappingTest {
}
@Test
@WithClasses(OrderMapper.class)
@ExpectedCompilationOutcome(
value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = OrderMapper.class,
kind = Kind.WARNING,
line = 41,
messageRegExp = "Mapping of Enums via @Mapping is going to be removed in future versions of "
+ "MapStruct\\. Please use @ValueMapping instead!")
}
)
public void shouldConsiderConstantMappings() {
ExternalOrderType target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.EXTRA );
assertThat( target ).isEqualTo( ExternalOrderType.SPECIAL );
@ -63,6 +85,17 @@ public class EnumMappingTest {
}
@Test
@WithClasses( OrderMapper.class )
@ExpectedCompilationOutcome(
value = CompilationResult.SUCCEEDED,
diagnostics = {
@Diagnostic(type = OrderMapper.class,
kind = Kind.WARNING,
line = 41,
messageRegExp = "Mapping of Enums via @Mapping is going to be removed in future versions of "
+ "MapStruct\\. Please use @ValueMapping instead!")
}
)
public void shouldInvokeEnumMappingMethodForPropertyMapping() {
OrderEntity order = new OrderEntity();
order.setOrderType( OrderType.EXTRA );
@ -73,15 +106,21 @@ public class EnumMappingTest {
}
@Test
@WithClasses(ErroneousOrderMapperMappingSameConstantTwice.class)
@WithClasses( ErroneousOrderMapperMappingSameConstantTwice.class )
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class,
kind = Kind.ERROR,
line = 42,
messageRegExp = "One enum constant must not be mapped to more than one target constant, but " +
"constant EXTRA is mapped to SPECIAL, DEFAULT\\.")
"constant EXTRA is mapped to SPECIAL, DEFAULT\\."),
@Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class,
kind = Kind.WARNING,
line = 42,
messageRegExp = "Mapping of Enums via @Mapping is going to be removed in future versions of "
+ "MapStruct\\. Please use @ValueMapping instead!")
}
)
public void shouldRaiseErrorIfSameSourceEnumConstantIsMappedTwice() {
@ -92,6 +131,11 @@ public class EnumMappingTest {
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.WARNING,
line = 40,
messageRegExp = "Mapping of Enums via @Mapping is going to be removed in future versions of "
+ "MapStruct\\. Please use @ValueMapping instead!"),
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.ERROR,
line = 37,
@ -115,7 +159,7 @@ public class EnumMappingTest {
kind = Kind.ERROR,
line = 34,
messageRegExp = "The following constants from the source enum have no corresponding constant in the " +
"target enum and must be be mapped via @Mapping: EXTRA, STANDARD, NORMAL")
"target enum and must be be mapped via adding additional mappings: EXTRA, STANDARD, NORMAL")
}
)
public void shouldRaiseErrorIfSourceConstantWithoutMatchingConstantInTargetTypeIsNotMapped() {

View File

@ -0,0 +1,42 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.prism;
import static org.fest.assertions.Assertions.assertThat;
import org.junit.Test;
import org.mapstruct.MappingConstants;
import org.mapstruct.ap.internal.prism.MappingConstantsPrism;
/**
* Test constants values
*
* @author Sjaak Derksen
*/
public class ConstantTest {
@Test
public void constantsShouldBeEqual() {
assertThat( MappingConstants.ANY_REMAINING ).isEqualTo( MappingConstantsPrism.ANY_REMAINING );
assertThat( MappingConstants.ANY_UNMAPPED ).isEqualTo( MappingConstantsPrism.ANY_UNMAPPED );
assertThat( MappingConstants.NULL ).isEqualTo( MappingConstantsPrism.NULL );
}
}

View File

@ -0,0 +1,38 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ValueMapping;
import org.mapstruct.factory.Mappers;
/**
* @author Sjaak Derksen
*/
@Mapper
public interface DefaultOrderMapper {
DefaultOrderMapper INSTANCE = Mappers.getMapper( DefaultOrderMapper.class );
OrderDto orderEntityToDto(OrderEntity order);
@ValueMapping( source = MappingConstants.ANY_UNMAPPED, target = "DEFAULT" )
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

View File

@ -0,0 +1,256 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import static org.fest.assertions.Assertions.assertThat;
import javax.tools.Diagnostic.Kind;
import org.junit.Test;
import org.junit.runner.RunWith;
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;
/**
* Test for the generation and invocation of enum mapping methods.
*
* @author Gunnar Morling, Sjaak Derksen
*/
@IssueKey("128")
@WithClasses({ OrderMapper.class, SpecialOrderMapper.class, DefaultOrderMapper.class, OrderEntity.class,
OrderType.class, OrderDto.class, ExternalOrderType.class })
@RunWith(AnnotationProcessorTestRunner.class)
public class EnumToEnumMappingTest {
@Test
public void shouldGenerateEnumMappingMethod() {
ExternalOrderType target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.B2B );
assertThat( target ).isEqualTo( ExternalOrderType.B2B );
target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.RETAIL );
assertThat( target ).isEqualTo( ExternalOrderType.RETAIL );
}
@Test
public void shouldConsiderConstantMappings() {
ExternalOrderType target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.EXTRA );
assertThat( target ).isEqualTo( ExternalOrderType.SPECIAL );
target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.STANDARD );
assertThat( target ).isEqualTo( ExternalOrderType.DEFAULT );
target = OrderMapper.INSTANCE.orderTypeToExternalOrderType( OrderType.NORMAL );
assertThat( target ).isEqualTo( ExternalOrderType.DEFAULT );
}
@Test
public void shouldInvokeEnumMappingMethodForPropertyMapping() {
OrderEntity order = new OrderEntity();
order.setOrderType( OrderType.EXTRA );
OrderDto orderDto = OrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.SPECIAL );
}
@Test
public void shouldApplyReverseMappings() {
OrderType result = OrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.SPECIAL );
assertThat( result ).isEqualTo( OrderType.EXTRA );
result = OrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.DEFAULT );
assertThat( result ).isEqualTo( OrderType.STANDARD );
result = OrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.RETAIL );
assertThat( result ).isEqualTo( OrderType.RETAIL );
result = OrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.B2B );
assertThat( result ).isEqualTo( OrderType.B2B );
}
@Test
public void shouldApplyNullMapping() {
OrderEntity order = new OrderEntity();
order.setOrderType( null );
OrderDto orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
}
@Test
public void shouldApplyTargetIsNullMapping() {
OrderEntity order = new OrderEntity();
order.setOrderType( OrderType.STANDARD );
OrderDto orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isNull();
}
@Test
public void shouldApplyDefaultMappings() {
OrderEntity order = new OrderEntity();
// try all other
order.setOrderType( OrderType.B2B );
OrderDto orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.B2B );
order.setOrderType( OrderType.EXTRA );
orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.SPECIAL );
order.setOrderType( OrderType.NORMAL );
orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.SPECIAL );
order.setOrderType( OrderType.RETAIL );
orderDto = SpecialOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.RETAIL );
}
@Test
public void shouldApplyDefaultReverseMappings() {
OrderType result = SpecialOrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.SPECIAL );
assertThat( result ).isEqualTo( OrderType.EXTRA );
result = SpecialOrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.DEFAULT );
assertThat( result ).isNull();
result = SpecialOrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.RETAIL );
assertThat( result ).isEqualTo( OrderType.RETAIL );
result = SpecialOrderMapper.INSTANCE.externalOrderTypeToOrderType( ExternalOrderType.B2B );
assertThat( result ).isEqualTo( OrderType.B2B );
}
@Test
public void shouldMappAllUnmappedToDefault() {
OrderEntity order = new OrderEntity();
order.setOrderType( OrderType.RETAIL );
OrderDto orderDto = DefaultOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
order.setOrderType( OrderType.B2B );
orderDto = DefaultOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
order.setOrderType( OrderType.EXTRA );
orderDto = DefaultOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
order.setOrderType( OrderType.STANDARD );
orderDto = DefaultOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
order.setOrderType( OrderType.NORMAL );
orderDto = DefaultOrderMapper.INSTANCE.orderEntityToDto( order );
assertThat( orderDto ).isNotNull();
assertThat( orderDto.getOrderType() ).isEqualTo( ExternalOrderType.DEFAULT );
}
@Test
@WithClasses(ErroneousOrderMapperMappingSameConstantTwice.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperMappingSameConstantTwice.class,
kind = Kind.ERROR,
line = 38,
messageRegExp = "Source value mapping: \"EXTRA\" cannot be mapped more than once\\.")
}
)
public void shouldRaiseErrorIfSameSourceEnumConstantIsMappedTwice() {
}
@Test
@WithClasses(ErroneousOrderMapperUsingUnknownEnumConstants.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.ERROR,
line = 37,
messageRegExp = "Constant FOO doesn't exist in enum type org.mapstruct.ap.test.value.OrderType\\."),
@Diagnostic(type = ErroneousOrderMapperUsingUnknownEnumConstants.class,
kind = Kind.ERROR,
line = 38,
messageRegExp = "Constant BAR doesn't exist in enum type org.mapstruct.ap.test.value." +
"ExternalOrderType\\.")
}
)
public void shouldRaiseErrorIfUnknownEnumConstantsAreSpecifiedInMapping() {
}
@Test
@WithClasses(ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class,
kind = Kind.ERROR,
line = 34,
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")
}
)
public void shouldRaiseErrorIfSourceConstantWithoutMatchingConstantInTargetTypeIsNotMapped() {
}
@Test
@WithClasses(ErroneousOrderMapperDuplicateANY.class)
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousOrderMapperDuplicateANY.class,
kind = Kind.ERROR,
line = 39,
messageRegExp = "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once\\." )
}
)
public void shouldRaiseErrorIfMappingsContainDuplicateANY() {
}
}

View File

@ -0,0 +1,42 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.factory.Mappers;
/**
* @author Sjaak Derksen
*/
@Mapper
public interface ErroneousOrderMapperDuplicateANY {
ErroneousOrderMapperDuplicateANY INSTANCE = Mappers.getMapper( ErroneousOrderMapperDuplicateANY.class );
@ValueMappings( {
@ValueMapping(source = "EXTRA", target = "SPECIAL"),
@ValueMapping(source = "STANDARD", target = "DEFAULT"),
@ValueMapping(source = "NORMAL", target = "DEFAULT"),
@ValueMapping( source = "<ANY_REMAINING>", target = "DEFAULT" ),
@ValueMapping( source = "<ANY_UNMAPPED>", target = "DEFAULT" )
} )
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

View File

@ -0,0 +1,43 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper
public interface ErroneousOrderMapperMappingSameConstantTwice {
ErroneousOrderMapperMappingSameConstantTwice INSTANCE = Mappers.getMapper(
ErroneousOrderMapperMappingSameConstantTwice.class
);
@ValueMappings({
@ValueMapping(source = "EXTRA", target = "SPECIAL"),
@ValueMapping(source = "EXTRA", target = "DEFAULT"),
@ValueMapping(source = "STANDARD", target = "DEFAULT"),
@ValueMapping(source = "NORMAL", target = "DEFAULT")
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

View File

@ -0,0 +1,35 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper
public interface ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType {
ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType INSTANCE = Mappers.getMapper(
ErroneousOrderMapperNotMappingConstantWithoutMatchInTargetType.class
);
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

View File

@ -0,0 +1,41 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper
public interface ErroneousOrderMapperUsingUnknownEnumConstants {
ErroneousOrderMapperUsingUnknownEnumConstants INSTANCE = Mappers.getMapper(
ErroneousOrderMapperUsingUnknownEnumConstants.class
);
@ValueMappings({
@ValueMapping(source = "FOO", target = "SPECIAL"),
@ValueMapping(source = "EXTRA", target = "BAR")
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
/**
* @author Gunnar Morling
*/
public enum ExternalOrderType {
RETAIL, B2B, SPECIAL, DEFAULT
}

View File

@ -0,0 +1,36 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
/**
* @author Gunnar Morling
*/
public class OrderDto {
private ExternalOrderType orderType;
public ExternalOrderType getOrderType() {
return orderType;
}
public void setOrderType(ExternalOrderType orderType) {
this.orderType = orderType;
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
/**
* @author Gunnar Morling
*/
public class OrderEntity {
private OrderType orderType;
public OrderType getOrderType() {
return orderType;
}
public void setOrderType(OrderType orderType) {
this.orderType = orderType;
}
}

View File

@ -0,0 +1,47 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper
public interface OrderMapper {
OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
OrderDto orderEntityToDto(OrderEntity order);
@ValueMappings({
@ValueMapping(source = "EXTRA", target = "SPECIAL"),
@ValueMapping(source = "STANDARD", target = "DEFAULT"),
@ValueMapping(source = "NORMAL", target = "DEFAULT")
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
@InheritInverseConfiguration
OrderType externalOrderTypeToOrderType(ExternalOrderType orderType);
}

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
/**
* @author Gunnar Morling
*/
public enum OrderType {
RETAIL, B2B, EXTRA, STANDARD, NORMAL
}

View File

@ -0,0 +1,48 @@
/**
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.value;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;
import org.mapstruct.factory.Mappers;
/**
* @author Sjaak Derksen
*/
@Mapper
public interface SpecialOrderMapper {
SpecialOrderMapper INSTANCE = Mappers.getMapper( SpecialOrderMapper.class );
OrderDto orderEntityToDto(OrderEntity order);
@ValueMappings({
@ValueMapping( source = MappingConstants.NULL, target = "DEFAULT" ),
@ValueMapping( source = "STANDARD", target = MappingConstants.NULL ),
@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "SPECIAL" )
})
ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
@InheritInverseConfiguration
@ValueMapping( target = "EXTRA", source = "SPECIAL" )
OrderType externalOrderTypeToOrderType(ExternalOrderType orderType);
}