#330 Making target() mandatory

This commit is contained in:
Gunnar Morling 2014-10-25 12:10:53 +02:00
parent 912ba714c1
commit 27bc599bca
18 changed files with 136 additions and 195 deletions

View File

@ -29,36 +29,41 @@ import java.util.Date;
/** /**
* Configures the mapping of one bean attribute or enum constant. * Configures the mapping of one bean attribute or enum constant.
* <p>
* The name of the mapped attribute or constant is to be specified via {@link #target()}. For mapped bean attributes it
* is assumed by default that the attribute has the same name in the source bean. Alternatively, one of
* {@link #source()}, {@link #expression()} or {@link #constant()} can be specified to define the property source.
* <p>
* In addition, the attributes {@link #dateFormat()} and {@link #qualifiedBy()} may be used to further define the
* mapping.
* *
* @author Gunnar Morling * @author Gunnar Morling
*/ */
@Retention( RetentionPolicy.SOURCE ) @Repeatable(Mappings.class)
@Target( ElementType.METHOD ) @Retention(RetentionPolicy.SOURCE)
@Repeatable( Mappings.class ) @Target(ElementType.METHOD)
public @interface Mapping { public @interface Mapping {
/** /**
* The source to use for this Mapping. This can either be: * The target name of the configured property as defined by the JavaBeans specification. If used to map an enum
* constant, the name of the constant member is to be given.
*
* @return The target name of the configured property or enum constant
*/
String target();
/**
* The source to use for this mapping. This can either be:
* <ol> * <ol>
* <li>The source name of the configured property as defined by the JavaBeans specification.</li> * <li>The source name of the configured property as defined by the JavaBeans specification.</li>
* <li>When used to map an enum constant, the name of the constant member is to be given.</li> * <li>When used to map an enum constant, the name of the constant member is to be given.</li>
* </ol> * </ol>
* Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping, but * Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping.
* not two at the same time. If this attribute is given, the target property must be specified via
* {@link #target()}.
* *
* @return The source name of the configured property or enum constant. * @return The source name of the configured property or enum constant.
*/ */
String source() default ""; String source() default "";
/**
* The target name of the configured property as defined by the JavaBeans specification. Defaults to the source name
* if not given. If used to map an enum constant, the name of the constant member is to be given.
*
* @return The target name of the configured property or enum constant
*/
String target() default "";
/** /**
* A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to * A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to
* {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants. * {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants.
@ -72,32 +77,29 @@ public @interface Mapping {
* property is not of type {@code String}, the value will be converted by applying a matching conversion method or * property is not of type {@code String}, the value will be converted by applying a matching conversion method or
* built-in conversion. * built-in conversion.
* <p> * <p>
* Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, but not * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping.
* two at the same time. If this attribute is given, the target property must be specified via {@link #target()}.
* *
* @return A constant {@code String} constant specifying the value for the designated target property * @return A constant {@code String} constant specifying the value for the designated target property
*/ */
String constant() default ""; String constant() default "";
/** /**
* An expression {@link String} based on which the specified target property is to be set. * An expression {@link String} based on which the specified target property is to be set. The format is determined
* * by a type of expression. For instance:
* The format is determined by a type of expression. For instance:
* {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java * {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java
* expression in the designated {@link #target()} property. * expression in the designated {@link #target()} property.
* <p> * <p>
* Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping, but not * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping.
* two at the same time. If this attribute is given, the target property must be specified via {@link #target()}.
* *
* @return A constant {@code String} constant specifying the value for the designated target property * @return A constant {@code String} constant specifying the value for the designated target property
*/ */
String expression() default ""; String expression() default "";
/** /**
* Whether the property specified via {@link #source()} or {@link #target()} should be ignored by the generated * Whether the property specified via {@link #target()} should be ignored by the generated mapping method or not.
* mapping method or not. This can be useful when certain attributes should not be propagated from source or target * This can be useful when certain attributes should not be propagated from source or target or when properties in
* or when properties in the target object are populated using a decorator and thus would be reported as unmapped * the target object are populated using a decorator and thus would be reported as unmapped target property by
* target property by default. * default.
* *
* @return {@code true} if the given property should be ignored, {@code false} otherwise * @return {@code true} if the given property should be ignored, {@code false} otherwise
*/ */
@ -105,9 +107,8 @@ public @interface Mapping {
/** /**
* A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple
* mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. * mapping methods (hand written or generated) qualify and thus would result in an 'Ambiguous mapping methods found'
* * error. A qualifier is a custom annotation and can be placed on a hand written mapper class or a method.
* A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method.
* *
* @return the qualifiers * @return the qualifiers
*/ */

View File

@ -28,6 +28,13 @@ import java.util.Date;
/** /**
* Configures the mapping of one bean attribute or enum constant. * Configures the mapping of one bean attribute or enum constant.
* <p>
* The name of the mapped attribute or constant is to be specified via {@link #target()}. For mapped bean attributes it
* is assumed by default that the attribute has the same name in the source bean. Alternatively, one of
* {@link #source()}, {@link #expression()} or {@link #constant()} can be specified to define the property source.
* <p>
* In addition, the attributes {@link #dateFormat()} and {@link #qualifiedBy()} may be used to further define the
* mapping.
* *
* @author Gunnar Morling * @author Gunnar Morling
*/ */
@ -36,27 +43,25 @@ import java.util.Date;
public @interface Mapping { public @interface Mapping {
/** /**
* The source to use for this Mapping. This can either be: * The target name of the configured property as defined by the JavaBeans specification. If used to map an enum
* constant, the name of the constant member is to be given.
*
* @return The target name of the configured property or enum constant
*/
String target();
/**
* The source to use for this mapping. This can either be:
* <ol> * <ol>
* <li>The source name of the configured property as defined by the JavaBeans specification.</li> * <li>The source name of the configured property as defined by the JavaBeans specification.</li>
* <li>When used to map an enum constant, the name of the constant member is to be given.</li> * <li>When used to map an enum constant, the name of the constant member is to be given.</li>
* </ol> * </ol>
* Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping, * Either this attribute or {@link #constant()} or {@link #expression()} may be specified for a given mapping.
* but not two at the same time. If this attribute is given, the target property must be specified via
* {@link #target()}.
* *
* @return The source name of the configured property or enum constant. * @return The source name of the configured property or enum constant.
*/ */
String source() default ""; String source() default "";
/**
* The target name of the configured property as defined by the JavaBeans specification. Defaults to the source name
* if not given. If used to map an enum constant, the name of the constant member is to be given.
*
* @return The target name of the configured property or enum constant
*/
String target() default "";
/** /**
* A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to * A format string as processable by {@link SimpleDateFormat} if the attribute is mapped from {@code String} to
* {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants. * {@link Date} or vice-versa. Will be ignored for all other attribute types and when mapping enum constants.
@ -66,38 +71,33 @@ public @interface Mapping {
String dateFormat() default ""; String dateFormat() default "";
/** /**
* A constant {@link String} based on which the specified target property is to be set. If the designated * A constant {@link String} based on which the specified target property is to be set. If the designated target
* target property is not of type {@code String}, the value will be converted by applying a matching conversion * property is not of type {@code String}, the value will be converted by applying a matching conversion method or
* method or built-in conversion. * built-in conversion.
* <p> * <p>
* Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping, * Either this attribute or {@link #source()} or {@link #expression()} may be specified for a given mapping.
* but not two at the same time. If this attribute is given, the target property must be specified via
* {@link #target()}.
* *
* @return A constant {@code String} constant specifying the value for the designated target property * @return A constant {@code String} constant specifying the value for the designated target property
*/ */
String constant() default ""; String constant() default "";
/** /**
* An expression {@link String} based on which the specified target property is to be set. * An expression {@link String} based on which the specified target property is to be set. The format is determined
* * by a type of expression. For instance:
* The format is determined by a type of expression. For instance:
* {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java * {@code expression = "java(new org.example.TimeAndFormat( s.getTime(), s.getFormat() ))")} will insert the java
* expression in the designated {@link #target()} property. * expression in the designated {@link #target()} property.
* <p> * <p>
* Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping, * Either this attribute or {@link #source()} or {@link #constant()} may be specified for a given mapping.
* but not two at the same time. If this attribute is given, the target property must be specified via
* {@link #target()}.
* *
* @return A constant {@code String} constant specifying the value for the designated target property * @return A constant {@code String} constant specifying the value for the designated target property
*/ */
String expression() default ""; String expression() default "";
/** /**
* Whether the property specified via {@link #source()} or {@link #target()} should be ignored by the generated * Whether the property specified via {@link #target()} should be ignored by the generated mapping method or not.
* mapping method or not. This can be useful when certain attributes should not be propagated from source or target * This can be useful when certain attributes should not be propagated from source or target or when properties in
* or when properties in the target object are populated using a decorator and thus would be reported as unmapped * the target object are populated using a decorator and thus would be reported as unmapped target property by
* target property by default. * default.
* *
* @return {@code true} if the given property should be ignored, {@code false} otherwise * @return {@code true} if the given property should be ignored, {@code false} otherwise
*/ */
@ -105,9 +105,8 @@ public @interface Mapping {
/** /**
* A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple * A qualifier can be specified to aid the selection process of a suitable mapper. This is useful in case multiple
* mappers (hand written of internal) qualify and result in an 'Ambiguous mapping methods found' error. * mapping methods (hand written or generated) qualify and thus would result in an 'Ambiguous mapping methods found'
* * error. A qualifier is a custom annotation and can be placed on a hand written mapper class or a method.
* A qualifier is a custom annotation and can be placed on either a hand written mapper class or a method.
* *
* @return the qualifiers * @return the qualifiers
*/ */

View File

@ -305,8 +305,7 @@ public class BeanMappingMethod extends MappingMethod {
} }
} }
else if ( mappedProperty.getConstant().isEmpty() else if ( mappedProperty.getSourcePropertyName() != null
&& mappedProperty.getJavaExpression().isEmpty()
&& !hasSourceProperty( mappedProperty.getSourcePropertyName() ) ) { && !hasSourceProperty( mappedProperty.getSourcePropertyName() ) ) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,

View File

@ -111,7 +111,8 @@ public class PropertyMapping extends ModelElement {
if ( mapping != null ) { if ( mapping != null ) {
dateFormat = mapping.getDateFormat(); dateFormat = mapping.getDateFormat();
qualifiers = mapping.getQualifiers(); qualifiers = mapping.getQualifiers();
sourcePropertyName = mapping.getSourcePropertyName(); sourcePropertyName =
mapping.getSourcePropertyName() == null ? targetPropertyName : mapping.getSourcePropertyName();
} }
else { else {
sourcePropertyName = targetPropertyName; sourcePropertyName = targetPropertyName;
@ -121,18 +122,7 @@ public class PropertyMapping extends ModelElement {
// then iterate over source accessors (assuming the source is a bean) // then iterate over source accessors (assuming the source is a bean)
for ( ExecutableElement sourceAccessor : sourceGetters ) { for ( ExecutableElement sourceAccessor : sourceGetters ) {
if ( Executables.getPropertyName( sourceAccessor ).equals( sourcePropertyName ) ) {
List<Mapping> sourceMappings = method.getMappings().get( sourcePropertyName );
if ( method.getMappings().containsKey( sourcePropertyName ) ) {
for ( Mapping sourceMapping : sourceMappings ) {
boolean mapsToOtherTarget = !sourceMapping.getTargetName().equals( targetPropertyName );
if ( Executables.getPropertyName( sourceAccessor ).equals( sourcePropertyName )
&& !mapsToOtherTarget ) {
return getPropertyMapping( sourceAccessor, dateFormat, qualifiers );
}
}
}
else if ( Executables.getPropertyName( sourceAccessor ).equals( sourcePropertyName ) ) {
return getPropertyMapping( sourceAccessor, dateFormat, qualifiers ); return getPropertyMapping( sourceAccessor, dateFormat, qualifiers );
} }
} }

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.processing.Messager; import javax.annotation.processing.Messager;
import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.AnnotationValue;
@ -53,7 +52,7 @@ public class Mapping {
private final String javaExpression; private final String javaExpression;
private final String targetName; private final String targetName;
private final String dateFormat; private final String dateFormat;
private final List<TypeMirror> qualifiers; private final List<TypeMirror> qualifiers;
private final boolean isIgnored; private final boolean isIgnored;
private final AnnotationMirror mirror; private final AnnotationMirror mirror;
private final AnnotationValue sourceAnnotationValue; private final AnnotationValue sourceAnnotationValue;
@ -85,18 +84,7 @@ public class Mapping {
mappingPrism.values.source() mappingPrism.values.source()
); );
if ( mappingPrism.source().isEmpty() && if ( !mappingPrism.source().isEmpty() && !mappingPrism.constant().isEmpty() ) {
mappingPrism.constant().isEmpty() &&
mappingPrism.expression().isEmpty() &&
!mappingPrism.ignore() ) {
messager.printMessage(
Diagnostic.Kind.ERROR,
"Either define a source, a constant or an expression in a Mapping",
element
);
return null;
}
else if ( !mappingPrism.source().isEmpty() && !mappingPrism.constant().isEmpty() ) {
messager.printMessage( messager.printMessage(
Diagnostic.Kind.ERROR, Diagnostic.Kind.ERROR,
"Source and constant are both defined in Mapping, either define a source or a constant", "Source and constant are both defined in Mapping, either define a source or a constant",
@ -120,10 +108,12 @@ public class Mapping {
); );
return null; return null;
} }
String source = mappingPrism.source().isEmpty() ? null : mappingPrism.source();
return new Mapping( return new Mapping(
mappingPrism.source(), source,
sourceNameParts != null ? sourceNameParts[0] : null, sourceNameParts != null ? sourceNameParts[0] : null,
sourceNameParts != null ? sourceNameParts[1] : mappingPrism.source(), sourceNameParts != null ? sourceNameParts[1] : source,
mappingPrism.constant(), mappingPrism.constant(),
mappingPrism.expression(), mappingPrism.expression(),
mappingPrism.target(), mappingPrism.target(),
@ -156,8 +146,8 @@ public class Mapping {
} }
//CHECKSTYLE:OFF //CHECKSTYLE:OFF
private Mapping( String sourceName, String sourceParameterName, String sourcePropertyName, String constant, private Mapping(String sourceName, String sourceParameterName, String sourcePropertyName, String constant,
String expression, String targetName, String dateFormat, List<TypeMirror> qualifiers, String expression, String targetName, String dateFormat, List<TypeMirror> qualifiers,
boolean isIgnored, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue, boolean isIgnored, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue,
AnnotationValue targetAnnotationValue) { AnnotationValue targetAnnotationValue) {
this.sourceName = sourceName; this.sourceName = sourceName;
@ -167,7 +157,7 @@ public class Mapping {
this.expression = expression; this.expression = expression;
Matcher javaExpressionMatcher = JAVA_EXPRESSION.matcher( expression ); Matcher javaExpressionMatcher = JAVA_EXPRESSION.matcher( expression );
this.javaExpression = javaExpressionMatcher.matches() ? javaExpressionMatcher.group( 1 ).trim() : ""; this.javaExpression = javaExpressionMatcher.matches() ? javaExpressionMatcher.group( 1 ).trim() : "";
this.targetName = targetName.equals( "" ) ? sourceName : targetName; this.targetName = targetName;
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
this.qualifiers = qualifiers; this.qualifiers = qualifiers;
this.isIgnored = isIgnored; this.isIgnored = isIgnored;
@ -246,12 +236,12 @@ public class Mapping {
// mapping can only be reversed if the source was not a constant nor an expression // mapping can only be reversed if the source was not a constant nor an expression
if ( constant.isEmpty() && expression.isEmpty() ) { if ( constant.isEmpty() && expression.isEmpty() ) {
reverse = new Mapping( reverse = new Mapping(
targetName, sourceName != null ? targetName : null,
null, null,
targetName, sourceName != null ? targetName : null,
constant, constant,
expression, expression,
sourceName, sourceName != null ? sourceName : targetName,
dateFormat, dateFormat,
qualifiers, qualifiers,
isIgnored, isIgnored,

View File

@ -29,6 +29,6 @@ public interface CalendarToStringMapper {
CalendarToStringMapper INSTANCE = Mappers.getMapper( CalendarToStringMapper.class ); CalendarToStringMapper INSTANCE = Mappers.getMapper( CalendarToStringMapper.class );
@Mapping( source = "prop", dateFormat = "dd.MM.yyyy" ) @Mapping( target = "prop", dateFormat = "dd.MM.yyyy" )
StringProperty map( CalendarProperty source ); StringProperty map( CalendarProperty source );
} }

View File

@ -29,6 +29,6 @@ public interface StringToCalendarMapper {
StringToCalendarMapper INSTANCE = Mappers.getMapper( StringToCalendarMapper.class ); StringToCalendarMapper INSTANCE = Mappers.getMapper( StringToCalendarMapper.class );
@Mapping( source = "prop", dateFormat = "dd.MM.yyyy" ) @Mapping( target = "prop", dateFormat = "dd.MM.yyyy" )
CalendarProperty map( StringProperty source); CalendarProperty map( StringProperty source);
} }

View File

@ -31,7 +31,7 @@ public interface StringToXmlGregCalMapper {
XmlGregorianCalendarProperty map(StringProperty source); XmlGregorianCalendarProperty map(StringProperty source);
@Mapping(source = "prop", dateFormat = "dd.MM.yyyy") @Mapping(target = "prop", dateFormat = "dd.MM.yyyy")
XmlGregorianCalendarProperty mapAndFormat(StringProperty source); XmlGregorianCalendarProperty mapAndFormat(StringProperty source);
} }

View File

@ -31,7 +31,7 @@ public interface XmlGregCalToStringMapper {
StringProperty map(XmlGregorianCalendarProperty source); StringProperty map(XmlGregorianCalendarProperty source);
@Mapping(source = "prop", dateFormat = "dd.MM.yyyy") @Mapping(target = "prop", dateFormat = "dd.MM.yyyy")
StringProperty mapAndFormat(XmlGregorianCalendarProperty source); StringProperty mapAndFormat(XmlGregorianCalendarProperty source);
} }

View File

@ -21,10 +21,10 @@ package org.mapstruct.ap.test.conversion.date;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.IterableMapping; import org.mapstruct.IterableMapping;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@Mapper @Mapper
@ -32,13 +32,15 @@ public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mapping(source = "date", dateFormat = "dd.MM.yyyy") @Mapping(target = "date", dateFormat = "dd.MM.yyyy")
Target sourceToTarget(Source source); Target sourceToTarget(Source source);
@InheritInverseConfiguration @InheritInverseConfiguration
Source targetToSource(Target target); Source targetToSource(Target target);
@IterableMapping(dateFormat = "dd.MM.yyyy") @IterableMapping(dateFormat = "dd.MM.yyyy")
List<String> stringListToDateList(List<Date> dates); List<String> stringListToDateList(List<Date> dates);
@InheritInverseConfiguration @InheritInverseConfiguration
List<Date> dateListToStringList(List<String> strings); List<Date> dateListToStringList(List<String> strings);
} }

View File

@ -39,46 +39,46 @@ public interface SourceTargetMapper {
String LOCAL_TIME_FORMAT = "HH:mm"; String LOCAL_TIME_FORMAT = "HH:mm";
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mappings( { @Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ), @Mappings( { @Mapping( target = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ),
@Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ), @Mapping( target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ),
@Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ), @Mapping( target = "localDate", dateFormat = LOCAL_DATE_FORMAT ),
@Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } ) @Mapping( target = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } )
Target sourceToTarget(Source source); Target sourceToTarget(Source source);
@Mappings( { @Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ), @Mappings( { @Mapping( target = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ),
@Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ), @Mapping( target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ),
@Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ), @Mapping( target = "localDate", dateFormat = LOCAL_DATE_FORMAT ),
@Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } ) @Mapping( target = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } )
Target sourceToTargetDefaultMapping(Source source); Target sourceToTargetDefaultMapping(Source source);
@Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ) @Mapping( target = "zonedDateTime", dateFormat = DATE_TIME_FORMAT )
Target sourceToTargetDateTimeMapped(Source source); Target sourceToTargetDateTimeMapped(Source source);
@Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ) @Mapping( target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT )
Target sourceToTargetLocalDateTimeMapped(Source source); Target sourceToTargetLocalDateTimeMapped(Source source);
@Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ) @Mapping( target = "localDate", dateFormat = LOCAL_DATE_FORMAT )
Target sourceToTargetLocalDateMapped(Source source); Target sourceToTargetLocalDateMapped(Source source);
@Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) @Mapping( target = "localTime", dateFormat = LOCAL_TIME_FORMAT )
Target sourceToTargetLocalTimeMapped(Source source); Target sourceToTargetLocalTimeMapped(Source source);
@Mappings( { @Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ), @Mappings( { @Mapping( target = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ),
@Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ), @Mapping( target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ),
@Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ), @Mapping( target = "localDate", dateFormat = LOCAL_DATE_FORMAT ),
@Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } ) @Mapping( target = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } )
Source targetToSource(Target target); Source targetToSource(Target target);
@Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ) @Mapping( target = "zonedDateTime", dateFormat = DATE_TIME_FORMAT )
Source targetToSourceDateTimeMapped(Target target); Source targetToSourceDateTimeMapped(Target target);
@Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ) @Mapping( target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT )
Source targetToSourceLocalDateTimeMapped(Target target); Source targetToSourceLocalDateTimeMapped(Target target);
@Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ) @Mapping( target = "localDate", dateFormat = LOCAL_DATE_FORMAT )
Source targetToSourceLocalDateMapped(Target target); Source targetToSourceLocalDateMapped(Target target);
@Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) @Mapping( target = "localTime", dateFormat = LOCAL_TIME_FORMAT )
Source targetToSourceLocalTimeMapped(Target target); Source targetToSourceLocalTimeMapped(Target target);
@InheritInverseConfiguration( name = "sourceToTarget" ) @InheritInverseConfiguration( name = "sourceToTarget" )

View File

@ -38,47 +38,46 @@ public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mappings({ @Mappings({
@Mapping(source = "dateTime", dateFormat = DATE_TIME_FORMAT), @Mapping(target = "dateTime", dateFormat = DATE_TIME_FORMAT),
@Mapping(source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT), @Mapping(target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT),
@Mapping(source = "localDate", dateFormat = LOCAL_DATE_FORMAT), @Mapping(target = "localDate", dateFormat = LOCAL_DATE_FORMAT),
@Mapping(source = "localTime", dateFormat = LOCAL_TIME_FORMAT) @Mapping(target = "localTime", dateFormat = LOCAL_TIME_FORMAT)
}) })
Target sourceToTarget(Source source); Target sourceToTarget(Source source);
@InheritInverseConfiguration( name = "targetToSource" ) // TODO: FIXME @InheritInverseConfiguration( name = "targetToSource" ) // TODO: FIXME
Target sourceToTargetDefaultMapping(Source source); Target sourceToTargetDefaultMapping(Source source);
@Mapping(source = "dateTime", dateFormat = DATE_TIME_FORMAT) @Mapping(target = "dateTime", dateFormat = DATE_TIME_FORMAT)
Target sourceToTargetDateTimeMapped(Source source); Target sourceToTargetDateTimeMapped(Source source);
@Mapping(source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT) @Mapping(target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT)
Target sourceToTargetLocalDateTimeMapped(Source source); Target sourceToTargetLocalDateTimeMapped(Source source);
@Mapping(source = "localDate", dateFormat = LOCAL_DATE_FORMAT) @Mapping(target = "localDate", dateFormat = LOCAL_DATE_FORMAT)
Target sourceToTargetLocalDateMapped(Source source); Target sourceToTargetLocalDateMapped(Source source);
@Mapping(source = "localTime", dateFormat = LOCAL_TIME_FORMAT) @Mapping(target = "localTime", dateFormat = LOCAL_TIME_FORMAT)
Target sourceToTargetLocalTimeMapped(Source source); Target sourceToTargetLocalTimeMapped(Source source);
@Mappings({ @Mappings({
@Mapping(source = "dateTime", dateFormat = DATE_TIME_FORMAT), @Mapping(target = "dateTime", dateFormat = DATE_TIME_FORMAT),
@Mapping(source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT), @Mapping(target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT),
@Mapping(source = "localDate", dateFormat = LOCAL_DATE_FORMAT), @Mapping(target = "localDate", dateFormat = LOCAL_DATE_FORMAT),
@Mapping(source = "localTime", dateFormat = LOCAL_TIME_FORMAT) @Mapping(target = "localTime", dateFormat = LOCAL_TIME_FORMAT)
}) })
Source targetToSource(Target target); Source targetToSource(Target target);
@Mapping(source = "dateTime", dateFormat = DATE_TIME_FORMAT) @Mapping(target = "dateTime", dateFormat = DATE_TIME_FORMAT)
Source targetToSourceDateTimeMapped(Target target); Source targetToSourceDateTimeMapped(Target target);
@Mapping(source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT) @Mapping(target = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT)
Source targetToSourceLocalDateTimeMapped(Target target); Source targetToSourceLocalDateTimeMapped(Target target);
@Mapping(source = "localDate", dateFormat = LOCAL_DATE_FORMAT) @Mapping(target = "localDate", dateFormat = LOCAL_DATE_FORMAT)
Source targetToSourceLocalDateMapped(Target target); Source targetToSourceLocalDateMapped(Target target);
@Mapping(source = "localTime", dateFormat = LOCAL_TIME_FORMAT) @Mapping(target = "localTime", dateFormat = LOCAL_TIME_FORMAT)
Source targetToSourceLocalTimeMapped(Target target); Source targetToSourceLocalTimeMapped(Target target);
@InheritInverseConfiguration( name = "sourceToTarget" ) // TODO: FIXME @InheritInverseConfiguration( name = "sourceToTarget" ) // TODO: FIXME

View File

@ -27,7 +27,7 @@ public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mapping( source = "object", ignore = true ) @Mapping( target = "object", ignore = true )
Target sourceToTarget(Source source); Target sourceToTarget(Source source);
Source targetToSource(Target target); Source targetToSource(Target target);

View File

@ -18,10 +18,9 @@
*/ */
package org.mapstruct.ap.test.ignore; package org.mapstruct.ap.test.ignore;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@Mapper @Mapper
@ -29,11 +28,9 @@ public interface AnimalMapper {
AnimalMapper INSTANCE = Mappers.getMapper( AnimalMapper.class ); AnimalMapper INSTANCE = Mappers.getMapper( AnimalMapper.class );
@Mappings({ @Mapping(target = "age", ignore = true)
@Mapping(source = "size", ignore = true),
@Mapping(target = "age", ignore = true)
})
AnimalDto animalToDto(Animal animal); AnimalDto animalToDto(Animal animal);
@InheritInverseConfiguration @InheritInverseConfiguration
Animal animalDtoToAnimal(AnimalDto animalDto); Animal animalDtoToAnimal(AnimalDto animalDto);
} }

View File

@ -18,14 +18,14 @@
*/ */
package org.mapstruct.ap.test.ignore; package org.mapstruct.ap.test.ignore;
import static org.fest.assertions.Assertions.assertThat;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.fest.assertions.Assertions.assertThat;
/** /**
* Test for ignoring properties during the mapping. * Test for ignoring properties during the mapping.
* *
@ -35,18 +35,6 @@ import static org.fest.assertions.Assertions.assertThat;
@RunWith(AnnotationProcessorTestRunner.class) @RunWith(AnnotationProcessorTestRunner.class)
public class IgnorePropertyTest { public class IgnorePropertyTest {
@Test
@IssueKey("72")
public void shouldNotPropagateIgnoredPropertyGivenViaSourceAttribute() {
Animal animal = new Animal( "Bruno", 100, 23 );
AnimalDto animalDto = AnimalMapper.INSTANCE.animalToDto( animal );
assertThat( animalDto ).isNotNull();
assertThat( animalDto.getName() ).isEqualTo( "Bruno" );
assertThat( animalDto.getSize() ).isNull();
}
@Test @Test
@IssueKey("72") @IssueKey("72")
public void shouldNotPropagateIgnoredPropertyGivenViaTargetAttribute() { public void shouldNotPropagateIgnoredPropertyGivenViaTargetAttribute() {

View File

@ -18,12 +18,12 @@
*/ */
package org.mapstruct.ap.test.selection.qualifier; package org.mapstruct.ap.test.selection.qualifier;
import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease;
import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated; import org.mapstruct.ap.test.selection.qualifier.annotation.NonQualifierAnnotated;
import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease;
import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease;
import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper;
import org.mapstruct.ap.test.selection.qualifier.handwritten.YetAnotherMapper; import org.mapstruct.ap.test.selection.qualifier.handwritten.YetAnotherMapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -38,7 +38,7 @@ public interface ErroneousMapper {
ErroneousMapper INSTANCE = Mappers.getMapper( ErroneousMapper.class ); ErroneousMapper INSTANCE = Mappers.getMapper( ErroneousMapper.class );
@Mappings( { @Mappings( {
@Mapping( source = "title", qualifiedBy = { NonQualifierAnnotated.class } ), } ) @Mapping( target = "title", qualifiedBy = { NonQualifierAnnotated.class } ), } )
GermanRelease toGerman( OriginalRelease movies ); GermanRelease toGerman( OriginalRelease movies );
} }

View File

@ -18,15 +18,15 @@
*/ */
package org.mapstruct.ap.test.selection.qualifier; package org.mapstruct.ap.test.selection.qualifier;
import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease;
import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease;
import org.mapstruct.ap.test.selection.qualifier.handwritten.Titles;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman; import org.mapstruct.ap.test.selection.qualifier.annotation.EnglishToGerman;
import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator; import org.mapstruct.ap.test.selection.qualifier.annotation.TitleTranslator;
import org.mapstruct.ap.test.selection.qualifier.bean.GermanRelease;
import org.mapstruct.ap.test.selection.qualifier.bean.OriginalRelease;
import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper; import org.mapstruct.ap.test.selection.qualifier.handwritten.SomeOtherMapper;
import org.mapstruct.ap.test.selection.qualifier.handwritten.Titles;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -39,7 +39,7 @@ public interface MovieMapper {
MovieMapper INSTANCE = Mappers.getMapper( MovieMapper.class ); MovieMapper INSTANCE = Mappers.getMapper( MovieMapper.class );
@Mappings( { @Mappings( {
@Mapping( source = "title", qualifiedBy = { TitleTranslator.class, EnglishToGerman.class } ), @Mapping( target = "title", qualifiedBy = { TitleTranslator.class, EnglishToGerman.class } )
} ) } )
GermanRelease toGerman( OriginalRelease movies ); GermanRelease toGerman( OriginalRelease movies );

View File

@ -18,10 +18,13 @@
*/ */
package org.mapstruct.ap.test.source.constants; package org.mapstruct.ap.test.source.constants;
import static org.fest.assertions.Assertions.assertThat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.Kind;
import org.junit.Test; import org.junit.Test;
@ -33,8 +36,6 @@ import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.fest.assertions.Assertions.assertThat;
/** /**
* @author Sjaak Derksen * @author Sjaak Derksen
*/ */
@ -159,31 +160,6 @@ public class SourceConstantsTest {
public void errorOnSourceAndExpression() throws ParseException { public void errorOnSourceAndExpression() throws ParseException {
} }
@Test
@IssueKey("187")
@WithClasses({
Source.class,
Target.class,
ErroneousMapper2.class,
StringListMapper.class
})
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousMapper2.class,
kind = Kind.ERROR,
line = 41,
messageRegExp = "Either define a source, a constant or an expression in a Mapping"),
@Diagnostic(type = ErroneousMapper2.class,
kind = Kind.WARNING,
line = 41,
messageRegExp = "Unmapped target property: \"integerConstant\"")
}
)
public void errorOnNeitherSourceNorExpression() throws ParseException {
}
@Test @Test
@IssueKey("255") @IssueKey("255")
@WithClasses({ @WithClasses({