#1401 improvements by direct assigning constants

This commit is contained in:
sjaakd 2018-04-01 15:15:42 +02:00
parent 2fe7f6be2b
commit 35f5400e00
17 changed files with 850 additions and 17 deletions

View File

@ -1918,7 +1918,8 @@ This chapter describes several advanced options which allow to fine-tune the beh
[[default-values-and-constants]]
=== Default values and constants
Default values can be specified to set a predefined value to a target property if the corresponding source property is `null`. Constants can be specified to set such a predefined value in any case. Default values and constants are specified as String values and are subject to type conversion either via built-in conversions or the invocation of other mapping methods in order to match the type required by the target property.
Default values can be specified to set a predefined value to a target property if the corresponding source property is `null`. Constants can be specified to set such a predefined value in any case. Default values and constants are specified as String values. When the target type is a primitive or a boxed type, the String value is taken literal. Bit / octal / decimal / hex patterns are allowed in such case as long as they are a valid literal.
In all other cases, constant or default values are subject to type conversion either via built-in conversions or the invocation of other mapping methods in order to match the type required by the target property.
A mapping with a constant must not include a reference to a source property. The following example shows some mappings using default values and constants:

View File

@ -496,13 +496,14 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
propertyMapping = new ConstantMappingBuilder()
.mappingContext( ctx )
.sourceMethod( method )
.constantExpression( "\"" + mapping.getConstant() + "\"" )
.constantExpression( mapping.getConstant() )
.targetProperty( targetProperty )
.targetPropertyName( mapping.getTargetName() )
.formattingParameters( mapping.getFormattingParameters() )
.selectionParameters( mapping.getSelectionParameters() )
.existingVariableNames( existingVariableNames )
.dependsOn( mapping.getDependsOn() )
.mirror( mapping.getMirror() )
.build();
handledTargets.add( mapping.getTargetName() );
}

View File

@ -23,6 +23,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.DeclaredType;
@ -116,6 +117,7 @@ public class PropertyMapping extends ModelElement {
protected List<String> dependsOn;
protected Set<String> existingVariableNames;
protected AnnotationMirror mirror;
MappingBuilderBase(Class<T> selfType) {
super( selfType );
@ -146,6 +148,11 @@ public class PropertyMapping extends ModelElement {
return (T) this;
}
T mirror(AnnotationMirror mirror) {
this.mirror = mirror;
return (T) this;
}
private Type determineTargetType() {
// This is a bean mapping method, so we know the result is a declared type
DeclaredType resultType = (DeclaredType) method.getResultType().getEffectiveType().getTypeMirror();
@ -359,7 +366,7 @@ public class PropertyMapping extends ModelElement {
&& ( !rhs.getSourceType().isPrimitive() || rhs.getSourcePresenceCheckerReference() != null) ) {
// cannot check on null source if source is primitive unless it has a presence checker
PropertyMapping build = new ConstantMappingBuilder()
.constantExpression( '"' + defaultValue + '"' )
.constantExpression( defaultValue )
.formattingParameters( formattingParameters )
.selectionParameters( selectionParameters )
.dependsOn( dependsOn )
@ -749,7 +756,12 @@ public class PropertyMapping extends ModelElement {
public PropertyMapping build() {
// source
String sourceErrorMessagePart = "constant '" + constantExpression + "'";
Type sourceType = ctx.getTypeFactory().getType( String.class );
Type sourceType = ctx.getTypeFactory().getTypeForConstant( targetType, constantExpression );
if ( String.class.getCanonicalName().equals( sourceType.getFullyQualifiedName() ) ) {
// convert to string
constantExpression = "\"" + constantExpression + "\"";
}
Assignment assignment = null;
if ( !targetType.isEnumType() ) {
@ -808,6 +820,7 @@ public class PropertyMapping extends ModelElement {
else {
ctx.getMessager().printMessage(
method.getExecutable(),
mirror,
Message.CONSTANTMAPPING_MAPPING_NOT_FOUND,
sourceType,
constantExpression,

View File

@ -89,6 +89,8 @@ public class Type extends ModelElement implements Comparable<Type> {
private final boolean isImported;
private final boolean isVoid;
private final boolean isStream;
private final boolean isBoxed;
private final boolean isOriginatedFromConstant;
private final List<String> enumConstants;
@ -111,7 +113,8 @@ public class Type extends ModelElement implements Comparable<Type> {
BuilderInfo builderInfo,
String packageName, String name, String qualifiedName,
boolean isInterface, boolean isEnumType, boolean isIterableType,
boolean isCollectionType, boolean isMapType, boolean isStreamType, boolean isImported) {
boolean isCollectionType, boolean isMapType, boolean isStreamType, boolean isImported,
boolean isBoxed, boolean isOriginatedFromConstant ) {
this.typeUtils = typeUtils;
this.elementUtils = elementUtils;
@ -135,6 +138,8 @@ public class Type extends ModelElement implements Comparable<Type> {
this.isStream = isStreamType;
this.isImported = isImported;
this.isVoid = typeMirror.getKind() == TypeKind.VOID;
this.isBoxed = isBoxed;
this.isOriginatedFromConstant = isOriginatedFromConstant;
if ( isEnumType ) {
enumConstants = new ArrayList<String>();
@ -384,7 +389,9 @@ public class Type extends ModelElement implements Comparable<Type> {
isCollectionType,
isMapType,
isStream,
isImported
isImported,
isBoxed,
isOriginatedFromConstant
);
}
@ -913,4 +920,13 @@ public class Type extends ModelElement implements Comparable<Type> {
return null;
}
public boolean isBoxed() {
return isBoxed;
}
public boolean hasOriginatedFromConstant() {
return isOriginatedFromConstant;
}
}

View File

@ -64,6 +64,7 @@ import org.mapstruct.ap.spi.BuilderInfo;
import org.mapstruct.ap.spi.BuilderProvider;
import org.mapstruct.ap.spi.DefaultBuilderProvider;
import org.mapstruct.ap.spi.TypeHierarchyErroneousException;
import org.mapstruct.ap.internal.util.NativeTypes;
import static org.mapstruct.ap.internal.model.common.ImplementationType.withDefaultConstructor;
import static org.mapstruct.ap.internal.model.common.ImplementationType.withInitialCapacity;
@ -131,6 +132,10 @@ public class TypeFactory {
}
public Type getType(String canonicalName) {
return getType( canonicalName, false );
}
private Type getType(String canonicalName, boolean isOriginatedFromConstant) {
TypeElement typeElement = elementUtils.getTypeElement( canonicalName );
if ( typeElement == null ) {
@ -139,7 +144,31 @@ public class TypeFactory {
);
}
return getType( typeElement );
return getType( typeElement, isOriginatedFromConstant );
}
public Type getTypeForConstant(Type targetType, String literal) {
Type result = null;
if ( targetType.isPrimitive() ) {
TypeKind kind = targetType.getTypeMirror().getKind();
boolean assignable = NativeTypes.isStringAssignable( kind, true, literal );
if ( assignable ) {
result = getType( targetType.getTypeMirror(), true );
}
}
else {
TypeKind boxedTypeKind = NativeTypes.getWrapperKind( targetType.getFullyQualifiedName() );
if ( boxedTypeKind != null ) {
boolean assignable = NativeTypes.isStringAssignable( boxedTypeKind, false, literal );
if ( assignable ) {
result = getType( targetType.getTypeMirror(), true );
}
}
}
if ( result == null ) {
result = getType( String.class.getCanonicalName(), true );
}
return result;
}
/**
@ -165,7 +194,15 @@ public class TypeFactory {
return getType( typeElement.asType() );
}
private Type getType(TypeElement typeElement, boolean originatedFromConstant) {
return getType( typeElement.asType(), originatedFromConstant );
}
public Type getType(TypeMirror mirror) {
return getType( mirror, false );
}
private Type getType(TypeMirror mirror, boolean originatedFromConstant) {
if ( !canBeProcessed( mirror ) ) {
throw new TypeHierarchyErroneousException( mirror );
}
@ -186,6 +223,7 @@ public class TypeFactory {
TypeElement typeElement;
Type componentType;
boolean isImported;
boolean isBoxed = false;
if ( mirror.getKind() == TypeKind.DECLARED ) {
DeclaredType declaredType = (DeclaredType) mirror;
@ -207,6 +245,7 @@ public class TypeFactory {
componentType = null;
isImported = isImported( name, qualifiedName );
isBoxed = NativeTypes.isWrapped( qualifiedName );
}
else if ( mirror.getKind() == TypeKind.ARRAY ) {
TypeMirror componentTypeMirror = getComponentType( mirror );
@ -267,7 +306,9 @@ public class TypeFactory {
isCollectionType,
isMapType,
isStreamType,
isImported
isImported,
isBoxed,
originatedFromConstant
);
}
@ -315,8 +356,8 @@ public class TypeFactory {
}
/**
* Get the Type for given method as part of usedMapper. Possibly parameterized types in method declaration
* will be evaluated to concrete types then.
* Get the Type for given method as part of usedMapper. Possibly parameterized types in method declaration will be
* evaluated to concrete types then.
*
* @param includingType the type on which's scope the method type shall be evaluated
* @param method the method
@ -479,7 +520,9 @@ public class TypeFactory {
implementationType.isCollectionType(),
implementationType.isMapType(),
implementationType.isStreamType(),
isImported( implementationType.getName(), implementationType.getFullyQualifiedName() )
isImported( implementationType.getName(), implementationType.getFullyQualifiedName() ),
implementationType.isBoxed(),
implementationType.hasOriginatedFromConstant()
);
return implementation.createNew( replacement );
}

View File

@ -253,6 +253,18 @@ public class MappingResolverImpl implements MappingResolver {
return simpleAssignment;
}
// At this point the SourceType will either
// 1. be a String
// 2. or when its a primitive / wrapped type and analysis successful equal to its TargetType. But in that
// case it should have been direct assignable.
// In case of 1. and the target type is still a wrapped or primitive type we must assume that the check
// in NativeType is not successful. We don't want to go through type conversion, double mappings etc.
// with something that we already know to be wrong.
if ( sourceType.hasOriginatedFromConstant() && ( targetType.isPrimitive() || targetType.isBoxed() ) ) {
// TODO: convey some error message
return null;
}
// then type conversion
Assignment conversion = resolveViaConversion( sourceType, targetType );
if ( conversion != null ) {

View File

@ -25,6 +25,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.lang.model.type.TypeKind;
/**
* Provides functionality around the Java primitive data types and their wrapper
@ -37,6 +39,195 @@ public class NativeTypes {
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPES;
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPES;
private static final Set<Class<?>> NUMBER_TYPES = new HashSet<Class<?>>();
private static final Map<String, TypeKind> WRAPPER_NAME_TO_PRIMITIVE_TYPES;
private static final Pattern PTRN_HEX = Pattern.compile( "^0[x|X].*" );
private static final Pattern PTRN_OCT = Pattern.compile( "^0_*[0-7].*" );
private static final Pattern PTRN_BIN = Pattern.compile( "^0[b|B].*" );
private static final Pattern PTRN_FLOAT_DEC_ZERO = Pattern.compile( "^[^eE]*[1-9].*[eE]?.*" );
private static final Pattern PTRN_FLOAT_HEX_ZERO = Pattern.compile( "^[^pP]*[1-9a-fA-F].*[pP]?.*" );
private static final Pattern PTRN_SIGN = Pattern.compile( "^[\\+|-]" );
private static final Pattern PTRN_LONG = Pattern.compile( "[l|L]$" );
private static final Pattern PTRN_FLOAT = Pattern.compile( "[f|F]$" );
private static final Pattern PTRN_DOUBLE = Pattern.compile( "[d|D]$" );
private static final Pattern PTRN_FAULTY_UNDERSCORE_INT = Pattern.compile( "^_|_$|-_|_-|\\+_|_\\+" );
private static final Pattern PTRN_FAULTY_UNDERSCORE_FLOAT = Pattern.compile( "^_|_$|-_|_-|\\+_|_\\+|\\._|_\\." );
private static final Pattern PTRN_FAULTY_DEC_UNDERSCORE_FLOAT = Pattern.compile( "_e|_E|e_|E_" );
private static final Pattern PTRN_FAULTY_HEX_UNDERSCORE_FLOAT = Pattern.compile( "_p|_P|p_|P_" );
private static final Map<TypeKind, NumberFormatValidator> VALIDATORS = initValidators();
private interface NumberFormatValidator {
boolean validate(boolean isPrimitive, String s);
}
private abstract static class NumberRepresentation {
int radix;
String val;
boolean isIntegralType;
boolean isLong;
boolean isFloat;
boolean isPrimitive;
NumberRepresentation(String in, boolean isIntegralType, boolean isLong, boolean isFloat, boolean isPrimitive) {
this.isLong = isLong;
this.isFloat = isFloat;
this.isIntegralType = isIntegralType;
this.isPrimitive = isPrimitive;
String valWithoutSign;
boolean isNegative = in.startsWith( "-" );
boolean hasSign = PTRN_SIGN.matcher( in ).find();
if ( hasSign ) {
valWithoutSign = in.substring( 1 );
}
else {
valWithoutSign = in;
}
if ( PTRN_HEX.matcher( valWithoutSign ).matches() ) {
// hex
radix = 16;
val = (isNegative ? "-" : "") + valWithoutSign.substring( 2 );
}
else if ( PTRN_BIN.matcher( valWithoutSign ).matches() ) {
// binary
radix = 2;
val = (isNegative ? "-" : "") + valWithoutSign.substring( 2 );
}
else if ( PTRN_OCT.matcher( valWithoutSign ).matches() ) {
// octal
radix = 8;
val = (isNegative ? "-" : "") + valWithoutSign.substring( 1 );
}
else {
// decimal
radix = 10;
val = (isNegative ? "-" : "") + valWithoutSign;
}
}
abstract boolean parse(String val, int radix);
boolean validate() {
try {
strip();
return parse( val, radix );
}
catch ( NumberFormatException ex ) {
return false;
}
}
void strip() {
if ( isIntegralType ) {
removeAndValidateIntegerLiteralSuffix();
removeAndValidateIntegerLiteralUnderscore();
}
else {
removeAndValidateFloatingPointLiteralSuffix();
removeAndValidateFloatingPointLiteralUnderscore();
}
}
/**
* remove java7+ underscores from the input
*/
void removeAndValidateIntegerLiteralUnderscore() {
if ( PTRN_FAULTY_UNDERSCORE_INT.matcher( val ).find() ) {
throw new NumberFormatException("Improperly placed underscores");
}
else {
val = val.replace( "_", "" );
}
}
/**
* remove java7+ underscores from the input
*/
void removeAndValidateFloatingPointLiteralUnderscore() {
boolean isHex = radix == 16;
if ( PTRN_FAULTY_UNDERSCORE_FLOAT.matcher( val ).find()
|| !isHex && PTRN_FAULTY_DEC_UNDERSCORE_FLOAT.matcher( val ).find()
|| isHex && PTRN_FAULTY_HEX_UNDERSCORE_FLOAT.matcher( val ).find() ) {
throw new NumberFormatException("Improperly placed underscores");
}
else {
val = val.replace( "_", "" );
}
}
/**
*
*/
void removeAndValidateIntegerLiteralSuffix() {
boolean endsWithLSuffix = PTRN_LONG.matcher( val ).find();
// error handling
if (endsWithLSuffix && !isLong) {
throw new NumberFormatException("L/l not allowed for non-long types");
}
if (!isPrimitive && !endsWithLSuffix && isLong) {
throw new NumberFormatException("L/l mandatory for boxed long");
}
// remove suffix
if ( endsWithLSuffix ) {
val = val.substring( 0, val.length() - 1 );
}
}
/**
* Double suffix forbidden for float.
*
* @param isFloat
*/
void removeAndValidateFloatingPointLiteralSuffix() {
boolean endsWithLSuffix = PTRN_LONG.matcher( val ).find();
boolean endsWithFSuffix = PTRN_FLOAT.matcher( val ).find();
boolean endsWithDSuffix = PTRN_DOUBLE.matcher( val ).find();
// error handling
if ( isFloat && endsWithDSuffix ) {
throw new NumberFormatException("Assiging double to a float");
}
// remove suffix
if ( endsWithLSuffix || endsWithFSuffix || endsWithDSuffix ) {
val = val.substring( 0, val.length() - 1 );
}
}
boolean floatHasBecomeZero(float parsed) {
if ( parsed == 0f ) {
return floatHasBecomeZero();
}
else {
return false;
}
}
boolean doubleHasBecomeZero(double parsed) {
if ( parsed == 0d ) {
return floatHasBecomeZero();
}
else {
return false;
}
}
private boolean floatHasBecomeZero() {
if ( radix == 10 ) {
// decimal, should be at least some number before exponent (eE) unequal to 0.
return PTRN_FLOAT_DEC_ZERO.matcher( val ).matches();
}
else {
// hex, should be at least some number before exponent (pP) unequal to 0.
return PTRN_FLOAT_HEX_ZERO.matcher( val ).matches();
}
}
}
private NativeTypes() {
}
@ -80,6 +271,19 @@ public class NativeTypes {
NUMBER_TYPES.add( Double.class );
NUMBER_TYPES.add( BigInteger.class );
NUMBER_TYPES.add( BigDecimal.class );
Map<String, TypeKind> tmp2 = new HashMap<String, TypeKind>();
tmp2.put( Boolean.class.getName(), TypeKind.BOOLEAN );
tmp2.put( Byte.class.getName(), TypeKind.BYTE );
tmp2.put( Character.class.getName(), TypeKind.CHAR );
tmp2.put( Double.class.getName(), TypeKind.DOUBLE );
tmp2.put( Float.class.getName(), TypeKind.FLOAT );
tmp2.put( Integer.class.getName(), TypeKind.INT );
tmp2.put( Long.class.getName(), TypeKind.LONG );
tmp2.put( Short.class.getName(), TypeKind.SHORT );
WRAPPER_NAME_TO_PRIMITIVE_TYPES = Collections.unmodifiableMap( tmp2 );
}
public static Class<?> getWrapperType(Class<?> clazz) {
@ -98,6 +302,14 @@ public class NativeTypes {
return WRAPPER_TO_PRIMITIVE_TYPES.get( clazz );
}
public static boolean isWrapped(String fullyQualifiedName) {
return WRAPPER_NAME_TO_PRIMITIVE_TYPES.containsKey( fullyQualifiedName );
}
public static TypeKind getWrapperKind(String fullyQualifiedName) {
return WRAPPER_NAME_TO_PRIMITIVE_TYPES.get( fullyQualifiedName );
}
public static boolean isNumber(Class<?> clazz) {
if ( clazz == null ) {
return false;
@ -106,4 +318,125 @@ public class NativeTypes {
return NUMBER_TYPES.contains( clazz );
}
}
public static boolean isStringAssignable(TypeKind kind, boolean isPrimitive, String in) {
NumberFormatValidator validator = VALIDATORS.get( kind );
return validator != null && validator.validate( isPrimitive, in );
}
private static Map<TypeKind, NumberFormatValidator> initValidators() {
Map<TypeKind, NumberFormatValidator> result = new HashMap<TypeKind, NumberFormatValidator>();
result.put( TypeKind.BOOLEAN, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
return "true".equals( s ) || "false".equals( s );
}
} );
result.put( TypeKind.CHAR, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
return s.length() == 3 && s.startsWith( "'" ) && s.endsWith( "'" );
}
} );
result.put( TypeKind.BYTE, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, true, false, false, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
Byte.parseByte( val, radix );
return true;
}
};
return br.validate();
}
} );
result.put( TypeKind.DOUBLE, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, false, false, false, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
Double d = Double.parseDouble( radix == 16 ? "0x" + val : val );
return !d.isInfinite() && !doubleHasBecomeZero( d );
}
};
return br.validate();
}
} );
result.put( TypeKind.FLOAT, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, false, false, true, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
Float f = Float.parseFloat( radix == 16 ? "0x" + val : val );
return !f.isInfinite() && !floatHasBecomeZero( f );
}
};
return br.validate();
}
} );
result.put( TypeKind.INT, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, true, false, false, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
if ( radix == 10 ) {
// when decimal: treat like signed
Integer.parseInt( val, radix );
return true;
}
else {
// when binary, octal or hex: treat like unsigned
return new BigInteger( val, radix ).bitLength() <= 32;
}
}
};
return br.validate();
}
} );
result.put( TypeKind.LONG, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, true, true, false, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
if ( radix == 10 ) {
// when decimal: treat like signed
Long.parseLong( val, radix );
return true;
}
else {
// when binary, octal or hex: treat like unsigned
return new BigInteger( val, radix ).bitLength() <= 64;
}
}
};
return br.validate();
}
} );
result.put( TypeKind.SHORT, new NumberFormatValidator() {
@Override
public boolean validate(boolean isPrimitive, String s) {
NumberRepresentation br = new NumberRepresentation( s, true, false, false, isPrimitive ) {
@Override
boolean parse(String val, int radix) {
Short.parseShort( val, radix );
return true;
}
};
return br.validate();
}
} );
return result;
}
}

View File

@ -183,6 +183,8 @@ public class DateFormatValidatorFactoryTest {
false,
false,
false,
false,
false,
false );
}

View File

@ -134,6 +134,8 @@ public class DefaultConversionContextTest {
false,
false,
false,
false,
false,
false );
}

View File

@ -0,0 +1,342 @@
/**
* Copyright 2012-2017 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.source.constants;
import javax.lang.model.type.TypeKind;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mapstruct.ap.internal.util.NativeTypes.isStringAssignable;
/**
*
* @author Sjaak Derksen
*/
public class ConstantOptimizingTest {
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* The following example shows other ways you can use the underscore in numeric literals:
*/
@Test
public void testUnderscorePlacement1() {
assertThat( isStringAssignable( TypeKind.LONG, true, "1234_5678_9012_3456L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "999_99_9999L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.14_15F" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0xFF_EC_DE_5EL" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0xCAFE_BABEL" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0x7fff_ffff_ffff_ffffL" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BYTE, true, "0b0010_0101" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0b11010010_01101001_10010100_10010010L" ) ).isTrue();
}
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* You can place underscores only between digits; you cannot place underscores in the following places:
* <ol>
* <li>At the beginning or end of a number</li>
* <li>Adjacent to a decimal point in a floating point literal</li>
* <li>Prior to an F or L suffix</li>
* <li>In positions where a string of digits is expected</li>
* </ol>
* The following examples demonstrate valid and invalid underscore placements (which are highlighted) in numeric
* literals:
*/
@Test
public void testUnderscorePlacement2() {
// Invalid: cannot put underscores
// adjacent to a decimal point
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3_.1415F" ) ).isFalse();
// Invalid: cannot put underscores
// adjacent to a decimal point
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3._1415F" ) ).isFalse();
// Invalid: cannot put underscores
// prior to an L suffix
assertThat( isStringAssignable( TypeKind.LONG, true, "999_99_9999_L" ) ).isFalse();
// OK (decimal literal)
assertThat( isStringAssignable( TypeKind.INT, true, "5_2" ) ).isTrue();
// Invalid: cannot put underscores
// At the end of a literal
assertThat( isStringAssignable( TypeKind.INT, true, "52_" ) ).isFalse();
// OK (decimal literal)
assertThat( isStringAssignable( TypeKind.INT, true, "5_______2" ) ).isTrue();
// Invalid: cannot put underscores
// in the 0x radix prefix
assertThat( isStringAssignable( TypeKind.INT, true, "0_x52" ) ).isFalse();
// Invalid: cannot put underscores
// at the beginning of a number
assertThat( isStringAssignable( TypeKind.INT, true, "0x_52" ) ).isFalse();
// OK (hexadecimal literal)
assertThat( isStringAssignable( TypeKind.INT, true, "0x5_2" ) ).isTrue();
// Invalid: cannot put underscores
// at the end of a number
assertThat( isStringAssignable( TypeKind.INT, true, "0x52_" ) ).isFalse();
}
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* The following example shows other ways you can use the underscore in numeric literals:
*/
@Test
public void testIntegerLiteralFromJLS() {
// largest positive int: dec / octal / int / binary
assertThat( isStringAssignable( TypeKind.INT, true, "2147483647" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0x7fff_ffff" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0177_7777_7777" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0b0111_1111_1111_1111_1111_1111_1111_1111" ) ).isTrue();
// most negative int: dec / octal / int / binary
// NOTE parseInt should be changed to parseUnsignedInt in Java, than the - sign can disssapear (java8)
// and the function will be true to what the compiler shows.
assertThat( isStringAssignable( TypeKind.INT, true, "-2147483648" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0x8000_0000" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0200_0000_0000" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0b1000_0000_0000_0000_0000_0000_0000_0000" ) ).isTrue();
// -1 representation int: dec / octal / int / binary
assertThat( isStringAssignable( TypeKind.INT, true, "-1" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0xffff_ffff" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0377_7777_7777" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0b1111_1111_1111_1111_1111_1111_1111_1111" ) ).isTrue();
// largest positive long: dec / octal / int / binary
assertThat( isStringAssignable( TypeKind.LONG, true, "9223372036854775807L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0x7fff_ffff_ffff_ffffL" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "07_7777_7777_7777_7777_7777L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_"
+ "1111_1111_1111_1111_1111_1111L" ) ).isTrue();
// most negative long: dec / octal / int / binary
assertThat( isStringAssignable( TypeKind.LONG, true, "-9223372036854775808L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0x8000_0000_0000_0000L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "010_0000_0000_0000_0000_0000L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_"
+ "0000_0000_0000_0000_0000L" ) ).isTrue();
// -1 representation long: dec / octal / int / binary
assertThat( isStringAssignable( TypeKind.LONG, true, "-1L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0xffff_ffff_ffff_ffffL" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "017_7777_7777_7777_7777_7777L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_"
+ "1111_1111_1111_1111_1111L" ) ).isTrue();
// some examples of ints
assertThat( isStringAssignable( TypeKind.INT, true, "0" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "2" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0372" ) ).isTrue();
//assertThat( isStringAssignable( TypeKind.INT, true, "0xDada_Cafe" ) ).isTrue(); java8
assertThat( isStringAssignable( TypeKind.INT, true, "1996" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "0x00_FF__00_FF" ) ).isTrue();
// some examples of longs
assertThat( isStringAssignable( TypeKind.LONG, true, "0777l" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0x100000000L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "2_147_483_648L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "0xC0B0L" ) ).isTrue();
}
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* The following example shows other ways you can use the underscore in numeric literals:
*/
@Test
public void testFloatingPoingLiteralFromJLS() {
// The largest positive finite literal of type float is 3.4028235e38f.
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.4028235e38f" ) ).isTrue();
// The smallest positive finite non-zero literal of type float is 1.40e-45f.
assertThat( isStringAssignable( TypeKind.FLOAT, true, "1.40e-45f" ) ).isTrue();
// The largest positive finite literal of type double is 1.7976931348623157e308.
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1.7976931348623157e308" ) ).isTrue();
// The smallest positive finite non-zero literal of type double is 4.9e-324
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9e-324" ) ).isTrue();
// some floats
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.1e1F" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "2.f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, ".3f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "0f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.14f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "6.022137e+23f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "-3.14f" ) ).isTrue();
// some doubles
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1e1" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1e+1" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "2." ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, ".3" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0.0" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "3.14" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "-3.14" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1e-9D" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1e137" ) ).isTrue();
// too large (infinitve)
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.4028235e38f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1.7976931348623157e308" ) ).isTrue();
// too large (infinitve)
assertThat( isStringAssignable( TypeKind.FLOAT, true, "3.4028235e39f" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "1.7976931348623159e308" ) ).isFalse();
// small
assertThat( isStringAssignable( TypeKind.FLOAT, true, "1.40e-45f" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "0x1.0p-149" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9e-324" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001P-1062d" ) ).isTrue();
// too small
assertThat( isStringAssignable( TypeKind.FLOAT, true, "1.40e-46f" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "0x1.0p-150" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9e-325" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001p-1063d" ) ).isFalse();
}
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* The following example shows other ways you can use the underscore in numeric literals:
*/
@Test
public void testBooleanLiteralFromJLS() {
assertThat( isStringAssignable( TypeKind.BOOLEAN, true, "true" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BOOLEAN, true, "false" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BOOLEAN, true, "FALSE" ) ).isFalse();
}
/**
* checkout https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
*
* The following example shows other ways you can use the underscore in numeric literals:
*/
@Test
public void testCharLiteralFromJLS() {
assertThat( isStringAssignable( TypeKind.CHAR, true, "'a'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'%'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\t'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\\'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\''" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\u03a9'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\uFFFF'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'\177'" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'Ω'" ) ).isTrue();
}
@Test
public void testShortAndByte() {
assertThat( isStringAssignable( TypeKind.SHORT, true, "0xFE" ) ).isTrue();
// some examples of ints
assertThat( isStringAssignable( TypeKind.BYTE, true, "0" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BYTE, true, "2" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BYTE, true, "127" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.BYTE, true, "-128" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.SHORT, true, "1996" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.SHORT, true, "-1996" ) ).isTrue();
}
@Test
public void testMiscellaneousErroneousPatterns() {
assertThat( isStringAssignable( TypeKind.INT, true, "1F" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "1D" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.INT, true, "_1" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.INT, true, "1_" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.INT, true, "0x_1" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.INT, true, "0_x1" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9e_-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9_e-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4._9e-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4_.9e-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "_4.9e-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9E-3_" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9E_-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9E-_3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9E+-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9E+_3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "4.9_E-3" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001_P-10d" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001P_-10d" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001_p-10d" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.DOUBLE, true, "0x0.001p_-10d" ) ).isFalse();
}
@Test
public void testNegatives() {
assertThat( isStringAssignable( TypeKind.INT, true, "-0xffaa" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "-0377_7777" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.INT, true, "-0b1111_1111" ) ).isTrue();
}
@Test
public void testFaultyChar() {
assertThat( isStringAssignable( TypeKind.CHAR, true, "''" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'a" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'aa" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "a'" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "aa'" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "'" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.CHAR, true, "a" ) ).isFalse();
}
@Test
public void testFloatWithLongLiteral() {
assertThat( isStringAssignable( TypeKind.FLOAT, true, "156L" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.FLOAT, true, "156l" ) ).isTrue();
}
@Test
public void testLongPrimitivesAndNonRequiredLongSuffix() {
assertThat( isStringAssignable( TypeKind.LONG, true, "156" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "156l" ) ).isTrue();
assertThat( isStringAssignable( TypeKind.LONG, true, "156L" ) ).isTrue();
}
@Test
public void testIntPrimitiveWithLongSuffix() {
assertThat( isStringAssignable( TypeKind.INT, true, "156l" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.INT, true, "156L" ) ).isFalse();
}
@Test
public void testTooBigIntegersAndBigLongs() {
assertThat( isStringAssignable( TypeKind.INT, true, "0xFFFF_FFFF_FFFF" ) ).isFalse();
assertThat( isStringAssignable( TypeKind.LONG, true, "0xFFFF_FFFF_FFFF_FFFF_FFFF" ) ).isFalse();
}
@Test
public void testNonSupportedPrimitiveType() {
assertThat( isStringAssignable( TypeKind.VOID, true, "0xFFFF_FFFF_FFFF" ) ).isFalse();
}
}

View File

@ -35,7 +35,7 @@ public interface ErroneousMapper1 {
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(source = "test", target = "integerConstant", constant = "14"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "longWrapperConstant", constant = "3001L"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "THE_NETHERLANDS")

View File

@ -35,7 +35,7 @@ public interface ErroneousMapper3 {
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(target = "integerConstant", expression = "java('test')", constant = "14"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "longWrapperConstant", constant = "3001L"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "THE_NETHERLANDS")

View File

@ -35,7 +35,7 @@ public interface ErroneousMapper4 {
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(source = "test", target = "integerConstant", expression = "java('test')"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "longWrapperConstant", constant = "3001L"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "THE_NETHERLANDS")

View File

@ -35,7 +35,7 @@ public interface ErroneousMapper5 {
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(target = "integerConstant", constant = "14"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "longWrapperConstant", constant = "3001L"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "DENMARK")

View File

@ -0,0 +1,46 @@
/**
* Copyright 2012-2017 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.source.constants;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
* @author Sjaak Derksen
*/
@Mapper(uses = StringListMapper.class)
public interface ErroneousMapper6 {
ErroneousMapper6 INSTANCE = Mappers.getMapper( ErroneousMapper6.class );
@Mappings({
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(target = "integerConstant", constant = "14"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "THE_NETHERLANDS")
})
Target sourceToTarget(Source s);
Source targetToSource(Target t);
}

View File

@ -209,7 +209,7 @@ public class SourceConstantsTest {
+ "constants.CountryEnum for property \"country\".$"),
@Diagnostic(type = ErroneousMapper5.class,
kind = Kind.ERROR,
line = 43,
line = 41,
messageRegExp = "^Can't map \"java.lang.String \"DENMARK\"\" to \"org.mapstruct.ap.test.source."
+ "constants.CountryEnum country\".$")
}
@ -217,6 +217,28 @@ public class SourceConstantsTest {
public void errorOnNonExistingEnumConstant() throws ParseException {
}
@Test
@IssueKey("1401")
@WithClasses({
Source.class,
Target.class,
CountryEnum.class,
ErroneousMapper6.class,
StringListMapper.class
})
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousMapper6.class,
kind = Kind.ERROR,
line = 38,
messageRegExp = "^.*Can't map \"java.lang.String \"3001\"\" to \"java.lang.Long "
+ "longWrapperConstant\".*$")
}
)
public void cannotMapIntConstantToLong() throws ParseException {
}
private Date getDate(String format, String date) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat( format );
Date result = dateFormat.parse( date );

View File

@ -35,7 +35,7 @@ public interface SourceTargetMapper {
@Mapping(target = "stringConstant", constant = "stringConstant"),
@Mapping(target = "emptyStringConstant", constant = ""),
@Mapping(target = "integerConstant", constant = "14"),
@Mapping(target = "longWrapperConstant", constant = "3001"),
@Mapping(target = "longWrapperConstant", constant = "3001L"),
@Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"),
@Mapping(target = "nameConstants", constant = "jack-jill-tom"),
@Mapping(target = "country", constant = "THE_NETHERLANDS")