mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#3323 Support access to the source property name
This commit is contained in:
parent
0a43bc088f
commit
8191c850e0
@ -24,6 +24,7 @@ import java.lang.annotation.Target;
|
|||||||
* <li>The mapping source parameter</li>
|
* <li>The mapping source parameter</li>
|
||||||
* <li>{@code @}{@link Context} parameter</li>
|
* <li>{@code @}{@link Context} parameter</li>
|
||||||
* <li>{@code @}{@link TargetPropertyName} parameter</li>
|
* <li>{@code @}{@link TargetPropertyName} parameter</li>
|
||||||
|
* <li>{@code @}{@link SourcePropertyName} parameter</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
||||||
|
26
core/src/main/java/org/mapstruct/SourcePropertyName.java
Normal file
26
core/src/main/java/org/mapstruct/SourcePropertyName.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This annotation marks a <em>presence check method</em> parameter as a source property name parameter.
|
||||||
|
* <p>
|
||||||
|
* This parameter enables conditional filtering based on source property name at run-time.
|
||||||
|
* Parameter must be of type {@link String} and can be present only in {@link Condition} method.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Oliver Erhart
|
||||||
|
* @since 1.6
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.CLASS)
|
||||||
|
public @interface SourcePropertyName {
|
||||||
|
}
|
@ -11,10 +11,10 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This annotation marks a <em>presence check method</em> parameter as a property name parameter.
|
* This annotation marks a <em>presence check method</em> parameter as a target property name parameter.
|
||||||
* <p>
|
* <p>
|
||||||
* This parameter enables conditional filtering based on target property name at run-time.
|
* This parameter enables conditional filtering based on target property name at run-time.
|
||||||
* Parameter must be of type {@link String} and can be present only in {@link Condition} method.
|
* Parameter must be of type {@link String} and can be present only in {@link Condition} method.
|
||||||
* </p>
|
* </p>
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
||||||
* @since 1.6
|
* @since 1.6
|
||||||
|
@ -406,9 +406,9 @@ public class CarMapperImpl implements CarMapper {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Additionally `@TargetPropertyName` of type `java.lang.String` can be used in custom condition check method:
|
Additionally `@TargetPropertyName` or `@SourcePropertyName` of type `java.lang.String` can be used in custom condition check method:
|
||||||
|
|
||||||
.Mapper using custom condition check method with `@TargetPropertyName`
|
.Mapper using custom condition check method with `@TargetPropertyName` and `@SourcePropertyName`
|
||||||
====
|
====
|
||||||
[source, java, linenums]
|
[source, java, linenums]
|
||||||
[subs="verbatim,attributes"]
|
[subs="verbatim,attributes"]
|
||||||
@ -416,11 +416,19 @@ Additionally `@TargetPropertyName` of type `java.lang.String` can be used in cus
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface CarMapper {
|
public interface CarMapper {
|
||||||
|
|
||||||
|
@Mapping(target = "owner", source = "ownerName")
|
||||||
CarDto carToCarDto(Car car, @MappingTarget CarDto carDto);
|
CarDto carToCarDto(Car car, @MappingTarget CarDto carDto);
|
||||||
|
|
||||||
@Condition
|
@Condition
|
||||||
default boolean isNotEmpty(String value, @TargetPropertyName String name) {
|
default boolean isNotEmpty(
|
||||||
if ( name.equals( "owner" ) {
|
String value,
|
||||||
|
@TargetPropertyName String targetPropertyName,
|
||||||
|
@SourcePropertyName String sourcePropertyName
|
||||||
|
) {
|
||||||
|
|
||||||
|
if ( targetPropertyName.equals( "owner" )
|
||||||
|
&& sourcePropertyName.equals( "ownerName" ) ) {
|
||||||
|
|
||||||
return value != null
|
return value != null
|
||||||
&& !value.isEmpty()
|
&& !value.isEmpty()
|
||||||
&& !value.equals( value.toLowerCase() );
|
&& !value.equals( value.toLowerCase() );
|
||||||
@ -431,7 +439,7 @@ public interface CarMapper {
|
|||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
The generated mapper with `@TargetPropertyName` will look like:
|
The generated mapper with `@TargetPropertyName` and `@SourcePropertyName` will look like:
|
||||||
|
|
||||||
.Custom condition check in generated implementation
|
.Custom condition check in generated implementation
|
||||||
====
|
====
|
||||||
@ -447,7 +455,7 @@ public class CarMapperImpl implements CarMapper {
|
|||||||
return carDto;
|
return carDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isNotEmpty( car.getOwner(), "owner" ) ) {
|
if ( isNotEmpty( car.getOwner(), "owner", "ownerName" ) ) {
|
||||||
carDto.setOwner( car.getOwner() );
|
carDto.setOwner( car.getOwner() );
|
||||||
} else {
|
} else {
|
||||||
carDto.setOwner( null );
|
carDto.setOwner( null );
|
||||||
@ -470,7 +478,7 @@ If there is a custom `@Condition` method applicable for the property it will hav
|
|||||||
====
|
====
|
||||||
Methods annotated with `@Condition` in addition to the value of the source property can also have the source parameter as an input.
|
Methods annotated with `@Condition` in addition to the value of the source property can also have the source parameter as an input.
|
||||||
|
|
||||||
`@TargetPropertyName` parameter can only be used in `@Condition` methods.
|
`@TargetPropertyName` and `@SourcePropertyName` parameters can only be used in `@Condition` methods.
|
||||||
====
|
====
|
||||||
|
|
||||||
<<selection-based-on-qualifiers>> is also valid for `@Condition` methods.
|
<<selection-based-on-qualifiers>> is also valid for `@Condition` methods.
|
||||||
|
@ -31,6 +31,7 @@ import org.mapstruct.Mappings;
|
|||||||
import org.mapstruct.Named;
|
import org.mapstruct.Named;
|
||||||
import org.mapstruct.ObjectFactory;
|
import org.mapstruct.ObjectFactory;
|
||||||
import org.mapstruct.Qualifier;
|
import org.mapstruct.Qualifier;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
import org.mapstruct.SubclassMapping;
|
import org.mapstruct.SubclassMapping;
|
||||||
import org.mapstruct.SubclassMappings;
|
import org.mapstruct.SubclassMappings;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
@ -57,6 +58,7 @@ import org.mapstruct.tools.gem.GemDefinition;
|
|||||||
@GemDefinition(BeanMapping.class)
|
@GemDefinition(BeanMapping.class)
|
||||||
@GemDefinition(EnumMapping.class)
|
@GemDefinition(EnumMapping.class)
|
||||||
@GemDefinition(MapMapping.class)
|
@GemDefinition(MapMapping.class)
|
||||||
|
@GemDefinition(SourcePropertyName.class)
|
||||||
@GemDefinition(SubclassMapping.class)
|
@GemDefinition(SubclassMapping.class)
|
||||||
@GemDefinition(SubclassMappings.class)
|
@GemDefinition(SubclassMappings.class)
|
||||||
@GemDefinition(TargetType.class)
|
@GemDefinition(TargetType.class)
|
||||||
|
@ -1522,6 +1522,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
MappingReferences mappingRefs = extractMappingReferences( targetPropertyName, false );
|
MappingReferences mappingRefs = extractMappingReferences( targetPropertyName, false );
|
||||||
PropertyMapping propertyMapping = new PropertyMappingBuilder().mappingContext( ctx )
|
PropertyMapping propertyMapping = new PropertyMappingBuilder().mappingContext( ctx )
|
||||||
.sourceMethod( method )
|
.sourceMethod( method )
|
||||||
|
.sourcePropertyName( targetPropertyName )
|
||||||
.target( targetPropertyName, targetPropertyReadAccessor, targetPropertyWriteAccessor )
|
.target( targetPropertyName, targetPropertyReadAccessor, targetPropertyWriteAccessor )
|
||||||
.sourceReference( sourceRef )
|
.sourceReference( sourceRef )
|
||||||
.existingVariableNames( existingVariableNames )
|
.existingVariableNames( existingVariableNames )
|
||||||
|
@ -70,6 +70,7 @@ import static org.mapstruct.ap.internal.model.common.Assignment.AssignmentType.D
|
|||||||
public class PropertyMapping extends ModelElement {
|
public class PropertyMapping extends ModelElement {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final String sourcePropertyName;
|
||||||
private final String sourceBeanName;
|
private final String sourceBeanName;
|
||||||
private final String targetWriteAccessorName;
|
private final String targetWriteAccessorName;
|
||||||
private final ReadAccessor targetReadAccessorProvider;
|
private final ReadAccessor targetReadAccessorProvider;
|
||||||
@ -286,6 +287,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new PropertyMapping(
|
return new PropertyMapping(
|
||||||
|
sourcePropertyName,
|
||||||
targetPropertyName,
|
targetPropertyName,
|
||||||
rightHandSide.getSourceParameterName(),
|
rightHandSide.getSourceParameterName(),
|
||||||
targetWriteAccessor.getSimpleName(),
|
targetWriteAccessor.getSimpleName(),
|
||||||
@ -1099,16 +1101,17 @@ public class PropertyMapping extends ModelElement {
|
|||||||
ReadAccessor targetReadAccessorProvider,
|
ReadAccessor targetReadAccessorProvider,
|
||||||
Type targetType, Assignment propertyAssignment,
|
Type targetType, Assignment propertyAssignment,
|
||||||
Set<String> dependsOn, Assignment defaultValueAssignment, boolean constructorMapping) {
|
Set<String> dependsOn, Assignment defaultValueAssignment, boolean constructorMapping) {
|
||||||
this( name, null, targetWriteAccessorName, targetReadAccessorProvider,
|
this( name, null, null, targetWriteAccessorName, targetReadAccessorProvider,
|
||||||
targetType, propertyAssignment, dependsOn, defaultValueAssignment,
|
targetType, propertyAssignment, dependsOn, defaultValueAssignment,
|
||||||
constructorMapping
|
constructorMapping
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PropertyMapping(String name, String sourceBeanName, String targetWriteAccessorName,
|
private PropertyMapping(String sourcePropertyName, String name, String sourceBeanName,
|
||||||
ReadAccessor targetReadAccessorProvider, Type targetType,
|
String targetWriteAccessorName, ReadAccessor targetReadAccessorProvider, Type targetType,
|
||||||
Assignment assignment,
|
Assignment assignment,
|
||||||
Set<String> dependsOn, Assignment defaultValueAssignment, boolean constructorMapping) {
|
Set<String> dependsOn, Assignment defaultValueAssignment, boolean constructorMapping) {
|
||||||
|
this.sourcePropertyName = sourcePropertyName;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.sourceBeanName = sourceBeanName;
|
this.sourceBeanName = sourceBeanName;
|
||||||
this.targetWriteAccessorName = targetWriteAccessorName;
|
this.targetWriteAccessorName = targetWriteAccessorName;
|
||||||
@ -1128,6 +1131,10 @@ public class PropertyMapping extends ModelElement {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSourcePropertyName() {
|
||||||
|
return sourcePropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSourceBeanName() {
|
public String getSourceBeanName() {
|
||||||
return sourceBeanName;
|
return sourceBeanName;
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,9 @@ import javax.lang.model.element.VariableElement;
|
|||||||
|
|
||||||
import org.mapstruct.ap.internal.gem.ContextGem;
|
import org.mapstruct.ap.internal.gem.ContextGem;
|
||||||
import org.mapstruct.ap.internal.gem.MappingTargetGem;
|
import org.mapstruct.ap.internal.gem.MappingTargetGem;
|
||||||
import org.mapstruct.ap.internal.gem.TargetTypeGem;
|
import org.mapstruct.ap.internal.gem.SourcePropertyNameGem;
|
||||||
import org.mapstruct.ap.internal.gem.TargetPropertyNameGem;
|
import org.mapstruct.ap.internal.gem.TargetPropertyNameGem;
|
||||||
|
import org.mapstruct.ap.internal.gem.TargetTypeGem;
|
||||||
import org.mapstruct.ap.internal.util.Collections;
|
import org.mapstruct.ap.internal.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +33,7 @@ public class Parameter extends ModelElement {
|
|||||||
private final boolean mappingTarget;
|
private final boolean mappingTarget;
|
||||||
private final boolean targetType;
|
private final boolean targetType;
|
||||||
private final boolean mappingContext;
|
private final boolean mappingContext;
|
||||||
|
private final boolean sourcePropertyName;
|
||||||
private final boolean targetPropertyName;
|
private final boolean targetPropertyName;
|
||||||
|
|
||||||
private final boolean varArgs;
|
private final boolean varArgs;
|
||||||
@ -44,12 +46,13 @@ public class Parameter extends ModelElement {
|
|||||||
this.mappingTarget = MappingTargetGem.instanceOn( element ) != null;
|
this.mappingTarget = MappingTargetGem.instanceOn( element ) != null;
|
||||||
this.targetType = TargetTypeGem.instanceOn( element ) != null;
|
this.targetType = TargetTypeGem.instanceOn( element ) != null;
|
||||||
this.mappingContext = ContextGem.instanceOn( element ) != null;
|
this.mappingContext = ContextGem.instanceOn( element ) != null;
|
||||||
|
this.sourcePropertyName = SourcePropertyNameGem.instanceOn( element ) != null;
|
||||||
this.targetPropertyName = TargetPropertyNameGem.instanceOn( element ) != null;
|
this.targetPropertyName = TargetPropertyNameGem.instanceOn( element ) != null;
|
||||||
this.varArgs = varArgs;
|
this.varArgs = varArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameter(String name, Type type, boolean mappingTarget, boolean targetType, boolean mappingContext,
|
private Parameter(String name, Type type, boolean mappingTarget, boolean targetType, boolean mappingContext,
|
||||||
boolean targetPropertyName,
|
boolean sourcePropertyName, boolean targetPropertyName,
|
||||||
boolean varArgs) {
|
boolean varArgs) {
|
||||||
this.element = null;
|
this.element = null;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -58,12 +61,13 @@ public class Parameter extends ModelElement {
|
|||||||
this.mappingTarget = mappingTarget;
|
this.mappingTarget = mappingTarget;
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
this.mappingContext = mappingContext;
|
this.mappingContext = mappingContext;
|
||||||
|
this.sourcePropertyName = sourcePropertyName;
|
||||||
this.targetPropertyName = targetPropertyName;
|
this.targetPropertyName = targetPropertyName;
|
||||||
this.varArgs = varArgs;
|
this.varArgs = varArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter(String name, Type type) {
|
public Parameter(String name, Type type) {
|
||||||
this( name, type, false, false, false, false, false );
|
this( name, type, false, false, false, false, false, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Element getElement() {
|
public Element getElement() {
|
||||||
@ -99,6 +103,7 @@ public class Parameter extends ModelElement {
|
|||||||
return ( mappingTarget ? "@MappingTarget " : "" )
|
return ( mappingTarget ? "@MappingTarget " : "" )
|
||||||
+ ( targetType ? "@TargetType " : "" )
|
+ ( targetType ? "@TargetType " : "" )
|
||||||
+ ( mappingContext ? "@Context " : "" )
|
+ ( mappingContext ? "@Context " : "" )
|
||||||
|
+ ( sourcePropertyName ? "@SourcePropertyName " : "" )
|
||||||
+ ( targetPropertyName ? "@TargetPropertyName " : "" )
|
+ ( targetPropertyName ? "@TargetPropertyName " : "" )
|
||||||
+ "%s " + name;
|
+ "%s " + name;
|
||||||
}
|
}
|
||||||
@ -120,6 +125,10 @@ public class Parameter extends ModelElement {
|
|||||||
return targetPropertyName;
|
return targetPropertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSourcePropertyName() {
|
||||||
|
return sourcePropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isVarArgs() {
|
public boolean isVarArgs() {
|
||||||
return varArgs;
|
return varArgs;
|
||||||
}
|
}
|
||||||
@ -165,6 +174,7 @@ public class Parameter extends ModelElement {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -206,6 +216,10 @@ public class Parameter extends ModelElement {
|
|||||||
return parameters.stream().filter( Parameter::isTargetType ).findAny().orElse( null );
|
return parameters.stream().filter( Parameter::isTargetType ).findAny().orElse( null );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Parameter getSourcePropertyNameParameter(List<Parameter> parameters) {
|
||||||
|
return parameters.stream().filter( Parameter::isSourcePropertyName ).findAny().orElse( null );
|
||||||
|
}
|
||||||
|
|
||||||
public static Parameter getTargetPropertyNameParameter(List<Parameter> parameters) {
|
public static Parameter getTargetPropertyNameParameter(List<Parameter> parameters) {
|
||||||
return parameters.stream().filter( Parameter::isTargetPropertyName ).findAny().orElse( null );
|
return parameters.stream().filter( Parameter::isTargetPropertyName ).findAny().orElse( null );
|
||||||
}
|
}
|
||||||
@ -214,6 +228,7 @@ public class Parameter extends ModelElement {
|
|||||||
return !parameter.isMappingTarget() &&
|
return !parameter.isMappingTarget() &&
|
||||||
!parameter.isTargetType() &&
|
!parameter.isTargetType() &&
|
||||||
!parameter.isMappingContext() &&
|
!parameter.isMappingContext() &&
|
||||||
|
!parameter.isSourcePropertyName() &&
|
||||||
!parameter.isTargetPropertyName();
|
!parameter.isTargetPropertyName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,16 +22,19 @@ public class ParameterBinding {
|
|||||||
private final boolean targetType;
|
private final boolean targetType;
|
||||||
private final boolean mappingTarget;
|
private final boolean mappingTarget;
|
||||||
private final boolean mappingContext;
|
private final boolean mappingContext;
|
||||||
|
private final boolean sourcePropertyName;
|
||||||
private final boolean targetPropertyName;
|
private final boolean targetPropertyName;
|
||||||
private final SourceRHS sourceRHS;
|
private final SourceRHS sourceRHS;
|
||||||
|
|
||||||
private ParameterBinding(Type parameterType, String variableName, boolean mappingTarget, boolean targetType,
|
private ParameterBinding(Type parameterType, String variableName, boolean mappingTarget, boolean targetType,
|
||||||
boolean mappingContext, boolean targetPropertyName, SourceRHS sourceRHS) {
|
boolean mappingContext, boolean sourcePropertyName, boolean targetPropertyName,
|
||||||
|
SourceRHS sourceRHS) {
|
||||||
this.type = parameterType;
|
this.type = parameterType;
|
||||||
this.variableName = variableName;
|
this.variableName = variableName;
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
this.mappingTarget = mappingTarget;
|
this.mappingTarget = mappingTarget;
|
||||||
this.mappingContext = mappingContext;
|
this.mappingContext = mappingContext;
|
||||||
|
this.sourcePropertyName = sourcePropertyName;
|
||||||
this.targetPropertyName = targetPropertyName;
|
this.targetPropertyName = targetPropertyName;
|
||||||
this.sourceRHS = sourceRHS;
|
this.sourceRHS = sourceRHS;
|
||||||
}
|
}
|
||||||
@ -64,11 +67,18 @@ public class ParameterBinding {
|
|||||||
return mappingContext;
|
return mappingContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true}, if the parameter being bound is a {@code @SourcePropertyName} parameter.
|
||||||
|
*/
|
||||||
|
public boolean isSourcePropertyName() {
|
||||||
|
return sourcePropertyName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code true}, if the parameter being bound is a {@code @TargetPropertyName} parameter.
|
* @return {@code true}, if the parameter being bound is a {@code @TargetPropertyName} parameter.
|
||||||
*/
|
*/
|
||||||
public boolean isTargetPropertyName() {
|
public boolean isTargetPropertyName() {
|
||||||
return targetPropertyName;
|
return targetPropertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,6 +118,7 @@ public class ParameterBinding {
|
|||||||
parameter.isMappingTarget(),
|
parameter.isMappingTarget(),
|
||||||
parameter.isTargetType(),
|
parameter.isTargetType(),
|
||||||
parameter.isMappingContext(),
|
parameter.isMappingContext(),
|
||||||
|
parameter.isSourcePropertyName(),
|
||||||
parameter.isTargetPropertyName(),
|
parameter.isTargetPropertyName(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
@ -129,6 +140,7 @@ public class ParameterBinding {
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -138,14 +150,21 @@ public class ParameterBinding {
|
|||||||
* @return a parameter binding representing a target type parameter
|
* @return a parameter binding representing a target type parameter
|
||||||
*/
|
*/
|
||||||
public static ParameterBinding forTargetTypeBinding(Type classTypeOf) {
|
public static ParameterBinding forTargetTypeBinding(Type classTypeOf) {
|
||||||
return new ParameterBinding( classTypeOf, null, false, true, false, false, null );
|
return new ParameterBinding( classTypeOf, null, false, true, false, false, false, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a parameter binding representing a target property name parameter
|
* @return a parameter binding representing a target property name parameter
|
||||||
*/
|
*/
|
||||||
public static ParameterBinding forTargetPropertyNameBinding(Type classTypeOf) {
|
public static ParameterBinding forTargetPropertyNameBinding(Type classTypeOf) {
|
||||||
return new ParameterBinding( classTypeOf, null, false, false, false, true, null );
|
return new ParameterBinding( classTypeOf, null, false, false, false, false, true, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a parameter binding representing a source property name parameter
|
||||||
|
*/
|
||||||
|
public static ParameterBinding forSourcePropertyNameBinding(Type classTypeOf) {
|
||||||
|
return new ParameterBinding( classTypeOf, null, false, false, false, true, false, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,7 +172,7 @@ public class ParameterBinding {
|
|||||||
* @return a parameter binding representing a mapping target parameter
|
* @return a parameter binding representing a mapping target parameter
|
||||||
*/
|
*/
|
||||||
public static ParameterBinding forMappingTargetBinding(Type resultType) {
|
public static ParameterBinding forMappingTargetBinding(Type resultType) {
|
||||||
return new ParameterBinding( resultType, null, true, false, false, false, null );
|
return new ParameterBinding( resultType, null, true, false, false, false, false, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,10 +180,10 @@ public class ParameterBinding {
|
|||||||
* @return a parameter binding representing a mapping source type
|
* @return a parameter binding representing a mapping source type
|
||||||
*/
|
*/
|
||||||
public static ParameterBinding forSourceTypeBinding(Type sourceType) {
|
public static ParameterBinding forSourceTypeBinding(Type sourceType) {
|
||||||
return new ParameterBinding( sourceType, null, false, false, false, false, null );
|
return new ParameterBinding( sourceType, null, false, false, false, false, false, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParameterBinding fromSourceRHS(SourceRHS sourceRHS) {
|
public static ParameterBinding fromSourceRHS(SourceRHS sourceRHS) {
|
||||||
return new ParameterBinding( sourceRHS.getSourceType(), null, false, false, false, false, sourceRHS );
|
return new ParameterBinding( sourceRHS.getSourceType(), null, false, false, false, false, false, sourceRHS );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ public class SourceMethod implements Method {
|
|||||||
private final List<Parameter> parameters;
|
private final List<Parameter> parameters;
|
||||||
private final Parameter mappingTargetParameter;
|
private final Parameter mappingTargetParameter;
|
||||||
private final Parameter targetTypeParameter;
|
private final Parameter targetTypeParameter;
|
||||||
|
private final Parameter sourcePropertyNameParameter;
|
||||||
private final Parameter targetPropertyNameParameter;
|
private final Parameter targetPropertyNameParameter;
|
||||||
private final boolean isObjectFactory;
|
private final boolean isObjectFactory;
|
||||||
private final boolean isPresenceCheck;
|
private final boolean isPresenceCheck;
|
||||||
@ -249,6 +250,7 @@ public class SourceMethod implements Method {
|
|||||||
|
|
||||||
this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
|
this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
|
||||||
this.targetTypeParameter = Parameter.getTargetTypeParameter( parameters );
|
this.targetTypeParameter = Parameter.getTargetTypeParameter( parameters );
|
||||||
|
this.sourcePropertyNameParameter = Parameter.getSourcePropertyNameParameter( parameters );
|
||||||
this.targetPropertyNameParameter = Parameter.getTargetPropertyNameParameter( parameters );
|
this.targetPropertyNameParameter = Parameter.getTargetPropertyNameParameter( parameters );
|
||||||
this.hasObjectFactoryAnnotation = ObjectFactoryGem.instanceOn( executable ) != null;
|
this.hasObjectFactoryAnnotation = ObjectFactoryGem.instanceOn( executable ) != null;
|
||||||
this.isObjectFactory = determineIfIsObjectFactory();
|
this.isObjectFactory = determineIfIsObjectFactory();
|
||||||
@ -265,9 +267,10 @@ public class SourceMethod implements Method {
|
|||||||
private boolean determineIfIsObjectFactory() {
|
private boolean determineIfIsObjectFactory() {
|
||||||
boolean hasNoSourceParameters = getSourceParameters().isEmpty();
|
boolean hasNoSourceParameters = getSourceParameters().isEmpty();
|
||||||
boolean hasNoMappingTargetParam = getMappingTargetParameter() == null;
|
boolean hasNoMappingTargetParam = getMappingTargetParameter() == null;
|
||||||
|
boolean hasNoSourcePropertyNameParam = getSourcePropertyNameParameter() == null;
|
||||||
boolean hasNoTargetPropertyNameParam = getTargetPropertyNameParameter() == null;
|
boolean hasNoTargetPropertyNameParam = getTargetPropertyNameParameter() == null;
|
||||||
return !isLifecycleCallbackMethod() && !returnType.isVoid()
|
return !isLifecycleCallbackMethod() && !returnType.isVoid()
|
||||||
&& hasNoMappingTargetParam && hasNoTargetPropertyNameParam
|
&& hasNoMappingTargetParam && hasNoSourcePropertyNameParam && hasNoTargetPropertyNameParam
|
||||||
&& ( hasObjectFactoryAnnotation || hasNoSourceParameters );
|
&& ( hasObjectFactoryAnnotation || hasNoSourceParameters );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +385,10 @@ public class SourceMethod implements Method {
|
|||||||
return targetTypeParameter;
|
return targetTypeParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Parameter getSourcePropertyNameParameter() {
|
||||||
|
return sourcePropertyNameParameter;
|
||||||
|
}
|
||||||
|
|
||||||
public Parameter getTargetPropertyNameParameter() {
|
public Parameter getTargetPropertyNameParameter() {
|
||||||
return targetPropertyNameParameter;
|
return targetPropertyNameParameter;
|
||||||
}
|
}
|
||||||
|
@ -171,6 +171,7 @@ public class SelectionContext {
|
|||||||
if ( sourceRHS != null ) {
|
if ( sourceRHS != null ) {
|
||||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||||
availableParams.add( ParameterBinding.fromSourceRHS( sourceRHS ) );
|
availableParams.add( ParameterBinding.fromSourceRHS( sourceRHS ) );
|
||||||
|
addSourcePropertyNameBindings( availableParams, sourceRHS.getSourceType(), typeFactory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||||
@ -189,6 +190,7 @@ public class SelectionContext {
|
|||||||
List<ParameterBinding> availableParams = new ArrayList<>();
|
List<ParameterBinding> availableParams = new ArrayList<>();
|
||||||
|
|
||||||
availableParams.add( ParameterBinding.forSourceTypeBinding( sourceType ) );
|
availableParams.add( ParameterBinding.forSourceTypeBinding( sourceType ) );
|
||||||
|
addSourcePropertyNameBindings( availableParams, sourceType, typeFactory );
|
||||||
|
|
||||||
for ( Parameter param : mappingMethod.getParameters() ) {
|
for ( Parameter param : mappingMethod.getParameters() ) {
|
||||||
if ( param.isMappingContext() ) {
|
if ( param.isMappingContext() ) {
|
||||||
@ -201,6 +203,22 @@ public class SelectionContext {
|
|||||||
return availableParams;
|
return availableParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addSourcePropertyNameBindings(List<ParameterBinding> availableParams, Type sourceType,
|
||||||
|
TypeFactory typeFactory) {
|
||||||
|
|
||||||
|
boolean sourcePropertyNameAvailable = false;
|
||||||
|
for ( ParameterBinding pb : availableParams ) {
|
||||||
|
if ( pb.isSourcePropertyName() ) {
|
||||||
|
sourcePropertyNameAvailable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !sourcePropertyNameAvailable ) {
|
||||||
|
availableParams.add( ParameterBinding.forSourcePropertyNameBinding( typeFactory.getType( String.class ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds default parameter bindings for the mapping-target and target-type if not already available.
|
* Adds default parameter bindings for the mapping-target and target-type if not already available.
|
||||||
*
|
*
|
||||||
|
@ -215,6 +215,7 @@ public class TypeSelector implements MethodSelector {
|
|||||||
if ( parameter.isTargetType() == candidate.isTargetType()
|
if ( parameter.isTargetType() == candidate.isTargetType()
|
||||||
&& parameter.isMappingTarget() == candidate.isMappingTarget()
|
&& parameter.isMappingTarget() == candidate.isMappingTarget()
|
||||||
&& parameter.isMappingContext() == candidate.isMappingContext()
|
&& parameter.isMappingContext() == candidate.isMappingContext()
|
||||||
|
&& parameter.isSourcePropertyName() == candidate.isSourcePropertyName()
|
||||||
&& parameter.isTargetPropertyName() == candidate.isTargetPropertyName()) {
|
&& parameter.isTargetPropertyName() == candidate.isTargetPropertyName()) {
|
||||||
result.add( candidate );
|
result.add( candidate );
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.mapstruct.ap.internal.gem.MapMappingGem;
|
|||||||
import org.mapstruct.ap.internal.gem.MappingGem;
|
import org.mapstruct.ap.internal.gem.MappingGem;
|
||||||
import org.mapstruct.ap.internal.gem.MappingsGem;
|
import org.mapstruct.ap.internal.gem.MappingsGem;
|
||||||
import org.mapstruct.ap.internal.gem.ObjectFactoryGem;
|
import org.mapstruct.ap.internal.gem.ObjectFactoryGem;
|
||||||
|
import org.mapstruct.ap.internal.gem.SourcePropertyNameGem;
|
||||||
import org.mapstruct.ap.internal.gem.SubclassMappingGem;
|
import org.mapstruct.ap.internal.gem.SubclassMappingGem;
|
||||||
import org.mapstruct.ap.internal.gem.SubclassMappingsGem;
|
import org.mapstruct.ap.internal.gem.SubclassMappingsGem;
|
||||||
import org.mapstruct.ap.internal.gem.TargetPropertyNameGem;
|
import org.mapstruct.ap.internal.gem.TargetPropertyNameGem;
|
||||||
@ -415,6 +416,16 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
|||||||
|
|
||||||
private boolean isValidPresenceCheckMethod(ExecutableElement method, List<Parameter> parameters, Type returnType) {
|
private boolean isValidPresenceCheckMethod(ExecutableElement method, List<Parameter> parameters, Type returnType) {
|
||||||
for ( Parameter param : parameters ) {
|
for ( Parameter param : parameters ) {
|
||||||
|
|
||||||
|
if ( param.isSourcePropertyName() && !param.getType().isString() ) {
|
||||||
|
messager.printMessage(
|
||||||
|
param.getElement(),
|
||||||
|
SourcePropertyNameGem.instanceOn( param.getElement() ).mirror(),
|
||||||
|
Message.RETRIEVAL_SOURCE_PROPERTY_NAME_WRONG_TYPE
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( param.isTargetPropertyName() && !param.getType().isString() ) {
|
if ( param.isTargetPropertyName() && !param.getType().isString() ) {
|
||||||
messager.printMessage(
|
messager.printMessage(
|
||||||
param.getElement(),
|
param.getElement(),
|
||||||
|
@ -177,6 +177,7 @@ public enum Message {
|
|||||||
RETRIEVAL_MAPPER_USES_CYCLE( "The mapper %s is referenced itself in Mapper#uses.", Diagnostic.Kind.WARNING ),
|
RETRIEVAL_MAPPER_USES_CYCLE( "The mapper %s is referenced itself in Mapper#uses.", Diagnostic.Kind.WARNING ),
|
||||||
RETRIEVAL_AFTER_METHOD_NOT_IMPLEMENTED( "@AfterMapping can only be applied to an implemented method." ),
|
RETRIEVAL_AFTER_METHOD_NOT_IMPLEMENTED( "@AfterMapping can only be applied to an implemented method." ),
|
||||||
RETRIEVAL_BEFORE_METHOD_NOT_IMPLEMENTED( "@BeforeMapping can only be applied to an implemented method." ),
|
RETRIEVAL_BEFORE_METHOD_NOT_IMPLEMENTED( "@BeforeMapping can only be applied to an implemented method." ),
|
||||||
|
RETRIEVAL_SOURCE_PROPERTY_NAME_WRONG_TYPE( "@SourcePropertyName can only by applied to a String parameter." ),
|
||||||
RETRIEVAL_TARGET_PROPERTY_NAME_WRONG_TYPE( "@TargetPropertyName can only by applied to a String parameter." ),
|
RETRIEVAL_TARGET_PROPERTY_NAME_WRONG_TYPE( "@TargetPropertyName can only by applied to a String parameter." ),
|
||||||
|
|
||||||
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
|
INHERITINVERSECONFIGURATION_DUPLICATES( "Several matching inverse methods exist: %s(). Specify a name explicitly." ),
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
<#if ext.targetBeanName??>${ext.targetBeanName}<#else>${param.variableName}</#if><#if ext.targetReadAccessorName??>.${ext.targetReadAccessorName}</#if><#t>
|
<#if ext.targetBeanName??>${ext.targetBeanName}<#else>${param.variableName}</#if><#if ext.targetReadAccessorName??>.${ext.targetReadAccessorName}</#if><#t>
|
||||||
<#elseif param.mappingContext>
|
<#elseif param.mappingContext>
|
||||||
${param.variableName}<#t>
|
${param.variableName}<#t>
|
||||||
|
<#elseif param.sourcePropertyName>
|
||||||
|
"${ext.sourcePropertyName}"<#t>
|
||||||
<#elseif param.targetPropertyName>
|
<#elseif param.targetPropertyName>
|
||||||
"${ext.targetPropertyName}"<#t>
|
"${ext.targetPropertyName}"<#t>
|
||||||
<#elseif param.sourceRHS??>
|
<#elseif param.sourceRHS??>
|
||||||
@ -60,7 +62,7 @@
|
|||||||
</#macro>
|
</#macro>
|
||||||
<#--
|
<#--
|
||||||
macro: assignment
|
macro: assignment
|
||||||
purpose: note: takes its targetyType from the singleSourceParameterType
|
purpose: note: takes its targetType from the singleSourceParameterType
|
||||||
-->
|
-->
|
||||||
<#macro _assignment assignmentToUse>
|
<#macro _assignment assignmentToUse>
|
||||||
<@includeModel object=assignmentToUse
|
<@includeModel object=assignmentToUse
|
||||||
@ -69,6 +71,7 @@
|
|||||||
existingInstanceMapping=ext.existingInstanceMapping
|
existingInstanceMapping=ext.existingInstanceMapping
|
||||||
targetReadAccessorName=ext.targetReadAccessorName
|
targetReadAccessorName=ext.targetReadAccessorName
|
||||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||||
|
sourcePropertyName=ext.sourcePropertyName
|
||||||
targetPropertyName=ext.targetPropertyName
|
targetPropertyName=ext.targetPropertyName
|
||||||
targetType=singleSourceParameterType/>
|
targetType=singleSourceParameterType/>
|
||||||
</#macro>
|
</#macro>
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.MethodReferencePresenceCheck" -->
|
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.MethodReferencePresenceCheck" -->
|
||||||
<#if isNegate()>!</#if><@includeModel object=methodReference
|
<#if isNegate()>!</#if><@includeModel object=methodReference
|
||||||
presenceCheck=true
|
presenceCheck=true
|
||||||
|
sourcePropertyName=ext.sourcePropertyName
|
||||||
targetPropertyName=ext.targetPropertyName
|
targetPropertyName=ext.targetPropertyName
|
||||||
targetType=ext.targetType/>
|
targetType=ext.targetType/>
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
existingInstanceMapping=ext.existingInstanceMapping
|
existingInstanceMapping=ext.existingInstanceMapping
|
||||||
targetReadAccessorName=targetReadAccessorName
|
targetReadAccessorName=targetReadAccessorName
|
||||||
targetWriteAccessorName=targetWriteAccessorName
|
targetWriteAccessorName=targetWriteAccessorName
|
||||||
|
sourcePropertyName=sourcePropertyName
|
||||||
targetPropertyName=name
|
targetPropertyName=name
|
||||||
targetType=targetType
|
targetType=targetType
|
||||||
defaultValueAssignment=defaultValueAssignment />
|
defaultValueAssignment=defaultValueAssignment />
|
@ -14,6 +14,7 @@ ${openExpression}<@_assignment/>${closeExpression}
|
|||||||
existingInstanceMapping=ext.existingInstanceMapping
|
existingInstanceMapping=ext.existingInstanceMapping
|
||||||
targetReadAccessorName=ext.targetReadAccessorName
|
targetReadAccessorName=ext.targetReadAccessorName
|
||||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||||
|
sourcePropertyName=ext.sourcePropertyName
|
||||||
targetPropertyName=ext.targetPropertyName
|
targetPropertyName=ext.targetPropertyName
|
||||||
targetType=ext.targetType/>
|
targetType=ext.targetType/>
|
||||||
</#macro>
|
</#macro>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<#if sourcePresenceCheckerReference??>
|
<#if sourcePresenceCheckerReference??>
|
||||||
if ( <@includeModel object=sourcePresenceCheckerReference
|
if ( <@includeModel object=sourcePresenceCheckerReference
|
||||||
targetPropertyName=ext.targetPropertyName
|
targetPropertyName=ext.targetPropertyName
|
||||||
|
sourcePropertyName=ext.sourcePropertyName
|
||||||
targetType=ext.targetType/> ) {
|
targetType=ext.targetType/> ) {
|
||||||
<#nested>
|
<#nested>
|
||||||
}
|
}
|
||||||
@ -61,6 +62,7 @@
|
|||||||
<#if sourcePresenceCheckerReference??>
|
<#if sourcePresenceCheckerReference??>
|
||||||
if ( <@includeModel object=sourcePresenceCheckerReference
|
if ( <@includeModel object=sourcePresenceCheckerReference
|
||||||
targetType=ext.targetType
|
targetType=ext.targetType
|
||||||
|
sourcePropertyName=ext.sourcePropertyName
|
||||||
targetPropertyName=ext.targetPropertyName /> ) {
|
targetPropertyName=ext.targetPropertyName /> ) {
|
||||||
<#if needs_explicit_local_var>
|
<#if needs_explicit_local_var>
|
||||||
<@includeModel object=nullCheckLocalVarType/> ${nullCheckLocalVarName} = <@lib.handleAssignment/>;
|
<@includeModel object=nullCheckLocalVarType/> ${nullCheckLocalVarName} = <@lib.handleAssignment/>;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target Property Name test entities
|
* Target Property Name test entities
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -15,14 +15,14 @@ public class EmployeeDto implements DomainModel {
|
|||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String title;
|
private String title;
|
||||||
private String country;
|
private String originCountry;
|
||||||
private boolean active;
|
private boolean active;
|
||||||
private int age;
|
private int age;
|
||||||
|
|
||||||
private EmployeeDto boss;
|
private EmployeeDto boss;
|
||||||
|
|
||||||
private AddressDto primaryAddress;
|
private AddressDto primaryAddress;
|
||||||
private List<AddressDto> addresses;
|
private List<AddressDto> originAddresses;
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
return firstName;
|
return firstName;
|
||||||
@ -48,12 +48,12 @@ public class EmployeeDto implements DomainModel {
|
|||||||
this.title = title;
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCountry() {
|
public String getOriginCountry() {
|
||||||
return country;
|
return originCountry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCountry(String country) {
|
public void setOriginCountry(String originCountry) {
|
||||||
this.country = country;
|
this.originCountry = originCountry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
@ -88,11 +88,11 @@ public class EmployeeDto implements DomainModel {
|
|||||||
this.primaryAddress = primaryAddress;
|
this.primaryAddress = primaryAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AddressDto> getAddresses() {
|
public List<AddressDto> getOriginAddresses() {
|
||||||
return addresses;
|
return originAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAddresses(List<AddressDto> addresses) {
|
public void setOriginAddresses(List<AddressDto> originAddresses) {
|
||||||
this.addresses = addresses;
|
this.originAddresses = originAddresses;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConditionalMethodForCollectionMapperWithSourcePropertyName {
|
||||||
|
|
||||||
|
ConditionalMethodForCollectionMapperWithSourcePropertyName INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodForCollectionMapperWithSourcePropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default <T> boolean isNotEmpty(Collection<T> collection, @SourcePropertyName String propName) {
|
||||||
|
if ( "originAddresses".equalsIgnoreCase( propName ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return collection != null && !collection.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotBlank(String value, @SourcePropertyName String propName) {
|
||||||
|
if ( propName.equalsIgnoreCase( "originCountry" ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Context;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConditionalMethodInMapperWithAllExceptTarget {
|
||||||
|
|
||||||
|
ConditionalMethodInMapperWithAllExceptTarget INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodInMapperWithAllExceptTarget.class );
|
||||||
|
|
||||||
|
class PresenceUtils {
|
||||||
|
Set<String> visited = new LinkedHashSet<>();
|
||||||
|
Set<String> visitedSources = new LinkedHashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotBlank(String value,
|
||||||
|
DomainModel source,
|
||||||
|
@SourcePropertyName String propName,
|
||||||
|
@Context PresenceUtils utils) {
|
||||||
|
utils.visited.add( propName );
|
||||||
|
utils.visitedSources.add( source.getClass().getSimpleName() );
|
||||||
|
if ( propName.equalsIgnoreCase( "firstName" ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Context;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConditionalMethodInMapperWithAllOptions {
|
||||||
|
|
||||||
|
ConditionalMethodInMapperWithAllOptions INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodInMapperWithAllOptions.class );
|
||||||
|
|
||||||
|
class PresenceUtils {
|
||||||
|
Set<String> visitedSourceNames = new LinkedHashSet<>();
|
||||||
|
Set<String> visitedTargetNames = new LinkedHashSet<>();
|
||||||
|
Set<String> visitedSources = new LinkedHashSet<>();
|
||||||
|
Set<String> visitedTargets = new LinkedHashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
void map(EmployeeDto employeeDto,
|
||||||
|
@MappingTarget Employee employee,
|
||||||
|
@Context PresenceUtils utils);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotBlank(String value,
|
||||||
|
DomainModel source,
|
||||||
|
@MappingTarget DomainModel target,
|
||||||
|
@SourcePropertyName String sourcePropName,
|
||||||
|
@TargetPropertyName String targetPropName,
|
||||||
|
@Context PresenceUtils utils) {
|
||||||
|
utils.visitedSourceNames.add( sourcePropName );
|
||||||
|
utils.visitedTargetNames.add( targetPropName );
|
||||||
|
utils.visitedSources.add( source.getClass().getSimpleName() );
|
||||||
|
utils.visitedTargets.add( target.getClass().getSimpleName() );
|
||||||
|
if ( sourcePropName.equalsIgnoreCase( "lastName" ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConditionalMethodInMapperWithSourcePropertyName {
|
||||||
|
|
||||||
|
ConditionalMethodInMapperWithSourcePropertyName INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodInMapperWithSourcePropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotBlank(String value, @SourcePropertyName String propName) {
|
||||||
|
if ( propName.equalsIgnoreCase( "originCountry" ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper(uses = ConditionalMethodInUsesMapperWithSourcePropertyName.PresenceUtils.class)
|
||||||
|
public interface ConditionalMethodInUsesMapperWithSourcePropertyName {
|
||||||
|
|
||||||
|
ConditionalMethodInUsesMapperWithSourcePropertyName INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodInUsesMapperWithSourcePropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
|
class PresenceUtils {
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
public boolean isNotBlank(String value, @SourcePropertyName String propName) {
|
||||||
|
if ( propName.equalsIgnoreCase( "originCountry" ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mapstruct.AfterMapping;
|
||||||
|
import org.mapstruct.BeforeMapping;
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Context;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.TargetType;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Address;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ConditionalMethodWithSourcePropertyNameInContextMapper {
|
||||||
|
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper INSTANCE
|
||||||
|
= Mappers.getMapper( ConditionalMethodWithSourcePropertyNameInContextMapper.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
||||||
|
|
||||||
|
Address map(AddressDto addressDto, @Context PresenceUtils utils);
|
||||||
|
|
||||||
|
class PresenceUtils {
|
||||||
|
Set<String> visited = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
public boolean isNotBlank(String value, @SourcePropertyName String propName) {
|
||||||
|
visited.add( propName );
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee, @Context PresenceUtilsAllProps utils);
|
||||||
|
|
||||||
|
Address map(AddressDto addressDto, @Context PresenceUtilsAllProps utils);
|
||||||
|
|
||||||
|
class PresenceUtilsAllProps {
|
||||||
|
Set<String> visited = new LinkedHashSet<>();
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
public boolean collect(@SourcePropertyName String propName) {
|
||||||
|
visited.add( propName );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee, @Context PresenceUtilsAllPropsWithSource utils);
|
||||||
|
|
||||||
|
Address map(AddressDto addressDto, @Context PresenceUtilsAllPropsWithSource utils);
|
||||||
|
|
||||||
|
@BeforeMapping
|
||||||
|
default void before(DomainModel source, @Context PresenceUtilsAllPropsWithSource utils) {
|
||||||
|
String lastProp = utils.visitedSegments.peekLast();
|
||||||
|
if ( lastProp != null && source != null ) {
|
||||||
|
utils.path.offerLast( lastProp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterMapping
|
||||||
|
default <T> void after(@TargetType Class<T> targetClass, @Context PresenceUtilsAllPropsWithSource utils) {
|
||||||
|
// intermediate method for collection mapping must not change the path
|
||||||
|
if (targetClass != List.class) {
|
||||||
|
utils.path.pollLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PresenceUtilsAllPropsWithSource {
|
||||||
|
Deque<String> visitedSegments = new LinkedList<>();
|
||||||
|
Deque<String> visited = new LinkedList<>();
|
||||||
|
Deque<String> path = new LinkedList<>();
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
public boolean collect(@SourcePropertyName String propName) {
|
||||||
|
visitedSegments.offerLast( propName );
|
||||||
|
path.offerLast( propName );
|
||||||
|
visited.offerLast( String.join( ".", path ) );
|
||||||
|
path.pollLast();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import org.mapstruct.Condition;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErroneousNonStringSourcePropertyNameParameter {
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
|
@Condition
|
||||||
|
default boolean isNotBlank(String value, @SourcePropertyName int propName) {
|
||||||
|
return value != null && !value.trim().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,312 @@
|
|||||||
|
/*
|
||||||
|
* Copyright MapStruct Authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.conditional.propertyname.sourcepropertyname;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Address;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
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.GeneratedSource;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
* @author Nikola Ivačič
|
||||||
|
* @author Mohammad Al Zouabi
|
||||||
|
* @author Oliver Erhart
|
||||||
|
*/
|
||||||
|
@IssueKey("3323")
|
||||||
|
@WithClasses({
|
||||||
|
Address.class,
|
||||||
|
AddressDto.class,
|
||||||
|
Employee.class,
|
||||||
|
EmployeeDto.class,
|
||||||
|
DomainModel.class
|
||||||
|
})
|
||||||
|
public class SourcePropertyNameTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
final GeneratedSource generatedSource = new GeneratedSource();
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodInMapperWithSourcePropertyName.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodInMapperWithSourcePropertyName() {
|
||||||
|
ConditionalMethodInMapperWithSourcePropertyName mapper
|
||||||
|
= ConditionalMethodInMapperWithSourcePropertyName.INSTANCE;
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setFirstName( " " );
|
||||||
|
employeeDto.setLastName( "Testirovich" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = mapper.map( employeeDto );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Testirovich" );
|
||||||
|
assertThat( employee.getFirstName() ).isNull();
|
||||||
|
assertThat( employee.getCountry() ).isNull();
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodForCollectionMapperWithSourcePropertyName.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodForCollectionMapperWithSourcePropertyName() {
|
||||||
|
ConditionalMethodForCollectionMapperWithSourcePropertyName mapper
|
||||||
|
= ConditionalMethodForCollectionMapperWithSourcePropertyName.INSTANCE;
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setFirstName( " " );
|
||||||
|
employeeDto.setLastName( "Testirovich" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = mapper.map( employeeDto );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Testirovich" );
|
||||||
|
assertThat( employee.getFirstName() ).isNull();
|
||||||
|
assertThat( employee.getCountry() ).isNull();
|
||||||
|
assertThat( employee.getAddresses() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodInUsesMapperWithSourcePropertyName.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodInUsesMapperWithSourcePropertyName() {
|
||||||
|
ConditionalMethodInUsesMapperWithSourcePropertyName mapper
|
||||||
|
= ConditionalMethodInUsesMapperWithSourcePropertyName.INSTANCE;
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setFirstName( " " );
|
||||||
|
employeeDto.setLastName( "Testirovich" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = mapper.map( employeeDto );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Testirovich" );
|
||||||
|
assertThat( employee.getFirstName() ).isNull();
|
||||||
|
assertThat( employee.getCountry() ).isNull();
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodInMapperWithAllOptions.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodInMapperWithAllOptions() {
|
||||||
|
ConditionalMethodInMapperWithAllOptions mapper
|
||||||
|
= ConditionalMethodInMapperWithAllOptions.INSTANCE;
|
||||||
|
|
||||||
|
ConditionalMethodInMapperWithAllOptions.PresenceUtils utils =
|
||||||
|
new ConditionalMethodInMapperWithAllOptions.PresenceUtils();
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setFirstName( " " );
|
||||||
|
employeeDto.setLastName( "Testirovich" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = new Employee();
|
||||||
|
mapper.map( employeeDto, employee, utils );
|
||||||
|
assertThat( employee.getLastName() ).isNull();
|
||||||
|
assertThat( employee.getFirstName() ).isNull();
|
||||||
|
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
assertThat( utils.visitedSourceNames )
|
||||||
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "originCountry" );
|
||||||
|
assertThat( utils.visitedTargetNames )
|
||||||
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "country" );
|
||||||
|
assertThat( utils.visitedSources ).containsExactly( "EmployeeDto" );
|
||||||
|
assertThat( utils.visitedTargets ).containsExactly( "Employee" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodInMapperWithAllExceptTarget.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodInMapperWithAllExceptTarget() {
|
||||||
|
ConditionalMethodInMapperWithAllExceptTarget mapper
|
||||||
|
= ConditionalMethodInMapperWithAllExceptTarget.INSTANCE;
|
||||||
|
|
||||||
|
ConditionalMethodInMapperWithAllExceptTarget.PresenceUtils utils =
|
||||||
|
new ConditionalMethodInMapperWithAllExceptTarget.PresenceUtils();
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setFirstName( " " );
|
||||||
|
employeeDto.setLastName( "Testirovich" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = mapper.map( employeeDto, utils );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Testirovich" );
|
||||||
|
assertThat( employee.getFirstName() ).isEqualTo( " " );
|
||||||
|
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
assertThat( utils.visited )
|
||||||
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "originCountry", "street" );
|
||||||
|
assertThat( utils.visitedSources ).containsExactlyInAnyOrder( "EmployeeDto", "AddressDto" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper.class
|
||||||
|
})
|
||||||
|
public void conditionalMethodWithSourcePropertyNameInUsesContextMapper() {
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper mapper
|
||||||
|
= ConditionalMethodWithSourcePropertyNameInContextMapper.INSTANCE;
|
||||||
|
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtils utils =
|
||||||
|
new ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtils();
|
||||||
|
|
||||||
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setLastName( " " );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
Employee employee = mapper.map( employeeDto, utils );
|
||||||
|
assertThat( employee.getLastName() ).isNull();
|
||||||
|
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
assertThat( utils.visited )
|
||||||
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "originCountry", "street" );
|
||||||
|
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtilsAllProps allPropsUtils =
|
||||||
|
new ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtilsAllProps();
|
||||||
|
|
||||||
|
employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setLastName( "Tester" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
employee = mapper.map( employeeDto, allPropsUtils );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Tester" );
|
||||||
|
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 6" );
|
||||||
|
assertThat( allPropsUtils.visited )
|
||||||
|
.containsExactlyInAnyOrder(
|
||||||
|
"firstName",
|
||||||
|
"lastName",
|
||||||
|
"title",
|
||||||
|
"originCountry",
|
||||||
|
"active",
|
||||||
|
"age",
|
||||||
|
"boss",
|
||||||
|
"primaryAddress",
|
||||||
|
"originAddresses",
|
||||||
|
"street"
|
||||||
|
);
|
||||||
|
|
||||||
|
ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtilsAllPropsWithSource allPropsUtilsWithSource =
|
||||||
|
new ConditionalMethodWithSourcePropertyNameInContextMapper.PresenceUtilsAllPropsWithSource();
|
||||||
|
|
||||||
|
EmployeeDto bossEmployeeDto = new EmployeeDto();
|
||||||
|
bossEmployeeDto.setLastName( "Boss Tester" );
|
||||||
|
bossEmployeeDto.setOriginCountry( "US" );
|
||||||
|
bossEmployeeDto.setOriginAddresses( Collections.singletonList( new AddressDto(
|
||||||
|
"Testing St. 10" ) ) );
|
||||||
|
|
||||||
|
employeeDto = new EmployeeDto();
|
||||||
|
employeeDto.setLastName( "Tester" );
|
||||||
|
employeeDto.setOriginCountry( "US" );
|
||||||
|
employeeDto.setBoss( bossEmployeeDto );
|
||||||
|
employeeDto.setOriginAddresses(
|
||||||
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
|
);
|
||||||
|
|
||||||
|
employee = mapper.map( employeeDto, allPropsUtilsWithSource );
|
||||||
|
assertThat( employee.getLastName() ).isEqualTo( "Tester" );
|
||||||
|
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getAddresses() ).isNotEmpty();
|
||||||
|
assertThat( employee.getAddresses().get( 0 ).getStreet() ).isEqualTo( "Testing St. 6" );
|
||||||
|
assertThat( employee.getBoss() ).isNotNull();
|
||||||
|
assertThat( employee.getBoss().getCountry() ).isEqualTo( "US" );
|
||||||
|
assertThat( employee.getBoss().getLastName() ).isEqualTo( "Boss Tester" );
|
||||||
|
assertThat( employee.getBoss().getAddresses() )
|
||||||
|
.extracting( Address::getStreet )
|
||||||
|
.containsExactly( "Testing St. 10" );
|
||||||
|
assertThat( allPropsUtilsWithSource.visited )
|
||||||
|
.containsExactly(
|
||||||
|
"originCountry",
|
||||||
|
"originAddresses",
|
||||||
|
"originAddresses.street",
|
||||||
|
"firstName",
|
||||||
|
"lastName",
|
||||||
|
"title",
|
||||||
|
"active",
|
||||||
|
"age",
|
||||||
|
"boss",
|
||||||
|
"boss.originCountry",
|
||||||
|
"boss.originAddresses",
|
||||||
|
"boss.originAddresses.street",
|
||||||
|
"boss.firstName",
|
||||||
|
"boss.lastName",
|
||||||
|
"boss.title",
|
||||||
|
"boss.active",
|
||||||
|
"boss.age",
|
||||||
|
"boss.boss",
|
||||||
|
"boss.primaryAddress",
|
||||||
|
"primaryAddress"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
@WithClasses({
|
||||||
|
ErroneousNonStringSourcePropertyNameParameter.class
|
||||||
|
})
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(
|
||||||
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
|
type = ErroneousNonStringSourcePropertyNameParameter.class,
|
||||||
|
line = 23,
|
||||||
|
message = "@SourcePropertyName can only by applied to a String parameter."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void nonStringSourcePropertyNameParameter() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -3,15 +3,18 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
||||||
*/
|
*/
|
||||||
@ -21,6 +24,8 @@ public interface ConditionalMethodForCollectionMapperWithTargetPropertyName {
|
|||||||
ConditionalMethodForCollectionMapperWithTargetPropertyName INSTANCE
|
ConditionalMethodForCollectionMapperWithTargetPropertyName INSTANCE
|
||||||
= Mappers.getMapper( ConditionalMethodForCollectionMapperWithTargetPropertyName.class );
|
= Mappers.getMapper( ConditionalMethodForCollectionMapperWithTargetPropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee);
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
@Condition
|
@Condition
|
@ -3,17 +3,21 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Context;
|
import org.mapstruct.Context;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Filip Hrisafov
|
* @author Filip Hrisafov
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
||||||
@ -29,6 +33,8 @@ public interface ConditionalMethodInMapperWithAllExceptTarget {
|
|||||||
Set<String> visitedSources = new LinkedHashSet<>();
|
Set<String> visitedSources = new LinkedHashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
||||||
|
|
||||||
@Condition
|
@Condition
|
@ -3,18 +3,23 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Context;
|
import org.mapstruct.Context;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.MappingTarget;
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.SourcePropertyName;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Filip Hrisafov
|
* @author Filip Hrisafov
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
||||||
@ -26,11 +31,14 @@ public interface ConditionalMethodInMapperWithAllOptions {
|
|||||||
= Mappers.getMapper( ConditionalMethodInMapperWithAllOptions.class );
|
= Mappers.getMapper( ConditionalMethodInMapperWithAllOptions.class );
|
||||||
|
|
||||||
class PresenceUtils {
|
class PresenceUtils {
|
||||||
Set<String> visited = new LinkedHashSet<>();
|
Set<String> visitedSourceNames = new LinkedHashSet<>();
|
||||||
|
Set<String> visitedTargetNames = new LinkedHashSet<>();
|
||||||
Set<String> visitedSources = new LinkedHashSet<>();
|
Set<String> visitedSources = new LinkedHashSet<>();
|
||||||
Set<String> visitedTargets = new LinkedHashSet<>();
|
Set<String> visitedTargets = new LinkedHashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
void map(EmployeeDto employeeDto,
|
void map(EmployeeDto employeeDto,
|
||||||
@MappingTarget Employee employee,
|
@MappingTarget Employee employee,
|
||||||
@Context PresenceUtils utils);
|
@Context PresenceUtils utils);
|
||||||
@ -39,12 +47,14 @@ public interface ConditionalMethodInMapperWithAllOptions {
|
|||||||
default boolean isNotBlank(String value,
|
default boolean isNotBlank(String value,
|
||||||
DomainModel source,
|
DomainModel source,
|
||||||
@MappingTarget DomainModel target,
|
@MappingTarget DomainModel target,
|
||||||
@TargetPropertyName String propName,
|
@SourcePropertyName String sourcePropName,
|
||||||
|
@TargetPropertyName String targetPropName,
|
||||||
@Context PresenceUtils utils) {
|
@Context PresenceUtils utils) {
|
||||||
utils.visited.add( propName );
|
utils.visitedSourceNames.add( sourcePropName );
|
||||||
|
utils.visitedTargetNames.add( targetPropName );
|
||||||
utils.visitedSources.add( source.getClass().getSimpleName() );
|
utils.visitedSources.add( source.getClass().getSimpleName() );
|
||||||
utils.visitedTargets.add( target.getClass().getSimpleName() );
|
utils.visitedTargets.add( target.getClass().getSimpleName() );
|
||||||
if ( propName.equalsIgnoreCase( "lastName" ) ) {
|
if ( targetPropName.equalsIgnoreCase( "lastName" ) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return value != null && !value.trim().isEmpty();
|
return value != null && !value.trim().isEmpty();
|
@ -3,11 +3,14 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,6 +23,8 @@ public interface ConditionalMethodInMapperWithTargetPropertyName {
|
|||||||
ConditionalMethodInMapperWithTargetPropertyName INSTANCE
|
ConditionalMethodInMapperWithTargetPropertyName INSTANCE
|
||||||
= Mappers.getMapper( ConditionalMethodInMapperWithTargetPropertyName.class );
|
= Mappers.getMapper( ConditionalMethodInMapperWithTargetPropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee);
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
@Condition
|
@Condition
|
@ -3,11 +3,14 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,6 +23,8 @@ public interface ConditionalMethodInUsesMapperWithTargetPropertyName {
|
|||||||
ConditionalMethodInUsesMapperWithTargetPropertyName INSTANCE
|
ConditionalMethodInUsesMapperWithTargetPropertyName INSTANCE
|
||||||
= Mappers.getMapper( ConditionalMethodInUsesMapperWithTargetPropertyName.class );
|
= Mappers.getMapper( ConditionalMethodInUsesMapperWithTargetPropertyName.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee);
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
class PresenceUtils {
|
class PresenceUtils {
|
@ -3,21 +3,29 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mapstruct.AfterMapping;
|
import org.mapstruct.AfterMapping;
|
||||||
import org.mapstruct.BeforeMapping;
|
import org.mapstruct.BeforeMapping;
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Context;
|
import org.mapstruct.Context;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.TargetType;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Address;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nikola Ivačič
|
* @author Nikola Ivačič
|
||||||
*/
|
*/
|
||||||
@ -27,6 +35,8 @@ public interface ConditionalMethodWithTargetPropertyNameInContextMapper {
|
|||||||
ConditionalMethodWithTargetPropertyNameInContextMapper INSTANCE
|
ConditionalMethodWithTargetPropertyNameInContextMapper INSTANCE
|
||||||
= Mappers.getMapper( ConditionalMethodWithTargetPropertyNameInContextMapper.class );
|
= Mappers.getMapper( ConditionalMethodWithTargetPropertyNameInContextMapper.class );
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
||||||
|
|
||||||
Address map(AddressDto addressDto, @Context PresenceUtils utils);
|
Address map(AddressDto addressDto, @Context PresenceUtils utils);
|
||||||
@ -41,6 +51,8 @@ public interface ConditionalMethodWithTargetPropertyNameInContextMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee, @Context PresenceUtilsAllProps utils);
|
Employee map(EmployeeDto employee, @Context PresenceUtilsAllProps utils);
|
||||||
|
|
||||||
Address map(AddressDto addressDto, @Context PresenceUtilsAllProps utils);
|
Address map(AddressDto addressDto, @Context PresenceUtilsAllProps utils);
|
||||||
@ -55,6 +67,8 @@ public interface ConditionalMethodWithTargetPropertyNameInContextMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee, @Context PresenceUtilsAllPropsWithSource utils);
|
Employee map(EmployeeDto employee, @Context PresenceUtilsAllPropsWithSource utils);
|
||||||
|
|
||||||
Address map(AddressDto addressDto, @Context PresenceUtilsAllPropsWithSource utils);
|
Address map(AddressDto addressDto, @Context PresenceUtilsAllPropsWithSource utils);
|
||||||
@ -68,8 +82,11 @@ public interface ConditionalMethodWithTargetPropertyNameInContextMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@AfterMapping
|
@AfterMapping
|
||||||
default void after(@Context PresenceUtilsAllPropsWithSource utils) {
|
default <T> void after(@TargetType Class<T> targetClass, @Context PresenceUtilsAllPropsWithSource utils) {
|
||||||
utils.path.pollLast();
|
// intermediate method for collection mapping must not change the path
|
||||||
|
if (targetClass != List.class) {
|
||||||
|
utils.path.pollLast();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PresenceUtilsAllPropsWithSource {
|
class PresenceUtilsAllPropsWithSource {
|
@ -3,15 +3,20 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
import org.mapstruct.Condition;
|
import org.mapstruct.Condition;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.TargetPropertyName;
|
import org.mapstruct.TargetPropertyName;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ErroneousNonStringTargetPropertyNameParameter {
|
public interface ErroneousNonStringTargetPropertyNameParameter {
|
||||||
|
|
||||||
|
@Mapping(target = "country", source = "originCountry")
|
||||||
|
@Mapping(target = "addresses", source = "originAddresses")
|
||||||
Employee map(EmployeeDto employee);
|
Employee map(EmployeeDto employee);
|
||||||
|
|
||||||
@Condition
|
@Condition
|
@ -3,9 +3,16 @@
|
|||||||
*
|
*
|
||||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
package org.mapstruct.ap.test.conditional.propertyname.targetpropertyname;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Address;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.AddressDto;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.DomainModel;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.Employee;
|
||||||
|
import org.mapstruct.ap.test.conditional.propertyname.EmployeeDto;
|
||||||
import org.mapstruct.ap.testutil.IssueKey;
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
import org.mapstruct.ap.testutil.ProcessorTest;
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
import org.mapstruct.ap.testutil.WithClasses;
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
@ -14,8 +21,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.GeneratedSource;
|
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,8 +51,8 @@ public class TargetPropertyNameTest {
|
|||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setFirstName( " " );
|
employeeDto.setFirstName( " " );
|
||||||
employeeDto.setLastName( "Testirovich" );
|
employeeDto.setLastName( "Testirovich" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -71,8 +76,8 @@ public class TargetPropertyNameTest {
|
|||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setFirstName( " " );
|
employeeDto.setFirstName( " " );
|
||||||
employeeDto.setLastName( "Testirovich" );
|
employeeDto.setLastName( "Testirovich" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -94,8 +99,8 @@ public class TargetPropertyNameTest {
|
|||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setFirstName( " " );
|
employeeDto.setFirstName( " " );
|
||||||
employeeDto.setLastName( "Testirovich" );
|
employeeDto.setLastName( "Testirovich" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -122,8 +127,8 @@ public class TargetPropertyNameTest {
|
|||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setFirstName( " " );
|
employeeDto.setFirstName( " " );
|
||||||
employeeDto.setLastName( "Testirovich" );
|
employeeDto.setLastName( "Testirovich" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -135,7 +140,9 @@ public class TargetPropertyNameTest {
|
|||||||
assertThat( employee.getAddresses() )
|
assertThat( employee.getAddresses() )
|
||||||
.extracting( Address::getStreet )
|
.extracting( Address::getStreet )
|
||||||
.containsExactly( "Testing St. 6" );
|
.containsExactly( "Testing St. 6" );
|
||||||
assertThat( utils.visited )
|
assertThat( utils.visitedSourceNames )
|
||||||
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "originCountry" );
|
||||||
|
assertThat( utils.visitedTargetNames )
|
||||||
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "country" );
|
.containsExactlyInAnyOrder( "firstName", "lastName", "title", "country" );
|
||||||
assertThat( utils.visitedSources ).containsExactly( "EmployeeDto" );
|
assertThat( utils.visitedSources ).containsExactly( "EmployeeDto" );
|
||||||
assertThat( utils.visitedTargets ).containsExactly( "Employee" );
|
assertThat( utils.visitedTargets ).containsExactly( "Employee" );
|
||||||
@ -155,8 +162,8 @@ public class TargetPropertyNameTest {
|
|||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setFirstName( " " );
|
employeeDto.setFirstName( " " );
|
||||||
employeeDto.setLastName( "Testirovich" );
|
employeeDto.setLastName( "Testirovich" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -185,8 +192,8 @@ public class TargetPropertyNameTest {
|
|||||||
|
|
||||||
EmployeeDto employeeDto = new EmployeeDto();
|
EmployeeDto employeeDto = new EmployeeDto();
|
||||||
employeeDto.setLastName( " " );
|
employeeDto.setLastName( " " );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -204,8 +211,8 @@ public class TargetPropertyNameTest {
|
|||||||
|
|
||||||
employeeDto = new EmployeeDto();
|
employeeDto = new EmployeeDto();
|
||||||
employeeDto.setLastName( "Tester" );
|
employeeDto.setLastName( "Tester" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -234,15 +241,15 @@ public class TargetPropertyNameTest {
|
|||||||
|
|
||||||
EmployeeDto bossEmployeeDto = new EmployeeDto();
|
EmployeeDto bossEmployeeDto = new EmployeeDto();
|
||||||
bossEmployeeDto.setLastName( "Boss Tester" );
|
bossEmployeeDto.setLastName( "Boss Tester" );
|
||||||
bossEmployeeDto.setCountry( "US" );
|
bossEmployeeDto.setOriginCountry( "US" );
|
||||||
bossEmployeeDto.setAddresses( Collections.singletonList( new AddressDto(
|
bossEmployeeDto.setOriginAddresses( Collections.singletonList( new AddressDto(
|
||||||
"Testing St. 10" ) ) );
|
"Testing St. 10" ) ) );
|
||||||
|
|
||||||
employeeDto = new EmployeeDto();
|
employeeDto = new EmployeeDto();
|
||||||
employeeDto.setLastName( "Tester" );
|
employeeDto.setLastName( "Tester" );
|
||||||
employeeDto.setCountry( "US" );
|
employeeDto.setOriginCountry( "US" );
|
||||||
employeeDto.setBoss( bossEmployeeDto );
|
employeeDto.setBoss( bossEmployeeDto );
|
||||||
employeeDto.setAddresses(
|
employeeDto.setOriginAddresses(
|
||||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -259,26 +266,26 @@ public class TargetPropertyNameTest {
|
|||||||
.containsExactly( "Testing St. 10" );
|
.containsExactly( "Testing St. 10" );
|
||||||
assertThat( allPropsUtilsWithSource.visited )
|
assertThat( allPropsUtilsWithSource.visited )
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
|
"country",
|
||||||
|
"addresses",
|
||||||
|
"addresses.street",
|
||||||
"firstName",
|
"firstName",
|
||||||
"lastName",
|
"lastName",
|
||||||
"title",
|
"title",
|
||||||
"country",
|
|
||||||
"active",
|
"active",
|
||||||
"age",
|
"age",
|
||||||
"boss",
|
"boss",
|
||||||
|
"boss.country",
|
||||||
|
"boss.addresses",
|
||||||
|
"boss.addresses.street",
|
||||||
"boss.firstName",
|
"boss.firstName",
|
||||||
"boss.lastName",
|
"boss.lastName",
|
||||||
"boss.title",
|
"boss.title",
|
||||||
"boss.country",
|
|
||||||
"boss.active",
|
"boss.active",
|
||||||
"boss.age",
|
"boss.age",
|
||||||
"boss.boss",
|
"boss.boss",
|
||||||
"boss.primaryAddress",
|
"boss.primaryAddress",
|
||||||
"boss.addresses",
|
"primaryAddress"
|
||||||
"boss.addresses.street",
|
|
||||||
"primaryAddress",
|
|
||||||
"addresses",
|
|
||||||
"addresses.street"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +300,7 @@ public class TargetPropertyNameTest {
|
|||||||
@Diagnostic(
|
@Diagnostic(
|
||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
type = ErroneousNonStringTargetPropertyNameParameter.class,
|
type = ErroneousNonStringTargetPropertyNameParameter.class,
|
||||||
line = 18,
|
line = 23,
|
||||||
message = "@TargetPropertyName can only by applied to a String parameter."
|
message = "@TargetPropertyName can only by applied to a String parameter."
|
||||||
)
|
)
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user