mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#2688: Support accessing to the target property name
This commit is contained in:
parent
62e73464b2
commit
8fa286fe4c
@ -23,6 +23,7 @@ import java.lang.annotation.Target;
|
||||
* e.g. the value given by calling {@code getName()} for the name property of the source bean</li>
|
||||
* <li>The mapping source parameter</li>
|
||||
* <li>{@code @}{@link Context} parameter</li>
|
||||
* <li>{@code @}{@link TargetPropertyName} parameter</li>
|
||||
* </ul>
|
||||
*
|
||||
* <strong>Note:</strong> The usage of this annotation is <em>mandatory</em>
|
||||
|
25
core/src/main/java/org/mapstruct/TargetPropertyName.java
Normal file
25
core/src/main/java/org/mapstruct/TargetPropertyName.java
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct;
|
||||
|
||||
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 property name parameter.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
* @author Nikola Ivačič
|
||||
* @since 1.6
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface TargetPropertyName {
|
||||
}
|
@ -404,6 +404,61 @@ public class CarMapperImpl implements CarMapper {
|
||||
----
|
||||
====
|
||||
|
||||
Additionally `@TargetPropertyName` of type `java.lang.String` can be used in custom condition check method:
|
||||
|
||||
.Mapper using custom condition check method with `@TargetPropertyName`
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
@Mapper
|
||||
public interface CarMapper {
|
||||
|
||||
CarDto carToCarDto(Car car, @MappingTarget CarDto carDto);
|
||||
|
||||
@Condition
|
||||
default boolean isNotEmpty(String value, @TargetPropertyName String name) {
|
||||
if ( name.equals( "owner" ) {
|
||||
return value != null
|
||||
&& !value.isEmpty()
|
||||
&& !value.equals( value.toLowerCase() );
|
||||
}
|
||||
return value != null && !value.isEmpty();
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
The generated mapper with `@TargetPropertyName` will look like:
|
||||
|
||||
.Custom condition check in generated implementation
|
||||
====
|
||||
[source, java, linenums]
|
||||
[subs="verbatim,attributes"]
|
||||
----
|
||||
// GENERATED CODE
|
||||
public class CarMapperImpl implements CarMapper {
|
||||
|
||||
@Override
|
||||
public CarDto carToCarDto(Car car, CarDto carDto) {
|
||||
if ( car == null ) {
|
||||
return carDto;
|
||||
}
|
||||
|
||||
if ( isNotEmpty( car.getOwner(), "owner" ) ) {
|
||||
carDto.setOwner( car.getOwner() );
|
||||
} else {
|
||||
carDto.setOwner( null );
|
||||
}
|
||||
|
||||
// Mapping of other properties
|
||||
|
||||
return carDto;
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
If there is a custom `@Condition` method applicable for the property it will have a precedence over a presence check method in the bean itself.
|
||||
@ -412,6 +467,8 @@ If there is a custom `@Condition` method applicable for the property it will hav
|
||||
[NOTE]
|
||||
====
|
||||
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.
|
||||
====
|
||||
|
||||
<<selection-based-on-qualifiers>> is also valid for `@Condition` methods.
|
||||
|
@ -30,6 +30,7 @@ import org.mapstruct.ObjectFactory;
|
||||
import org.mapstruct.Qualifier;
|
||||
import org.mapstruct.SubclassMapping;
|
||||
import org.mapstruct.SubclassMappings;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.TargetType;
|
||||
import org.mapstruct.ValueMapping;
|
||||
import org.mapstruct.ValueMappings;
|
||||
@ -52,6 +53,7 @@ import org.mapstruct.tools.gem.GemDefinition;
|
||||
@GemDefinition(SubclassMapping.class)
|
||||
@GemDefinition(SubclassMappings.class)
|
||||
@GemDefinition(TargetType.class)
|
||||
@GemDefinition(TargetPropertyName.class)
|
||||
@GemDefinition(MappingTarget.class)
|
||||
@GemDefinition(DecoratedWith.class)
|
||||
@GemDefinition(MapperConfig.class)
|
||||
|
@ -15,6 +15,7 @@ import javax.lang.model.element.VariableElement;
|
||||
import org.mapstruct.ap.internal.gem.ContextGem;
|
||||
import org.mapstruct.ap.internal.gem.MappingTargetGem;
|
||||
import org.mapstruct.ap.internal.gem.TargetTypeGem;
|
||||
import org.mapstruct.ap.internal.gem.TargetPropertyNameGem;
|
||||
import org.mapstruct.ap.internal.util.Collections;
|
||||
|
||||
/**
|
||||
@ -31,6 +32,7 @@ public class Parameter extends ModelElement {
|
||||
private final boolean mappingTarget;
|
||||
private final boolean targetType;
|
||||
private final boolean mappingContext;
|
||||
private final boolean targetPropertyName;
|
||||
|
||||
private final boolean varArgs;
|
||||
|
||||
@ -42,10 +44,12 @@ public class Parameter extends ModelElement {
|
||||
this.mappingTarget = MappingTargetGem.instanceOn( element ) != null;
|
||||
this.targetType = TargetTypeGem.instanceOn( element ) != null;
|
||||
this.mappingContext = ContextGem.instanceOn( element ) != null;
|
||||
this.targetPropertyName = TargetPropertyNameGem.instanceOn( element ) != null;
|
||||
this.varArgs = varArgs;
|
||||
}
|
||||
|
||||
private Parameter(String name, Type type, boolean mappingTarget, boolean targetType, boolean mappingContext,
|
||||
boolean targetPropertyName,
|
||||
boolean varArgs) {
|
||||
this.element = null;
|
||||
this.name = name;
|
||||
@ -54,11 +58,12 @@ public class Parameter extends ModelElement {
|
||||
this.mappingTarget = mappingTarget;
|
||||
this.targetType = targetType;
|
||||
this.mappingContext = mappingContext;
|
||||
this.targetPropertyName = targetPropertyName;
|
||||
this.varArgs = varArgs;
|
||||
}
|
||||
|
||||
public Parameter(String name, Type type) {
|
||||
this( name, type, false, false, false, false );
|
||||
this( name, type, false, false, false, false, false );
|
||||
}
|
||||
|
||||
public Element getElement() {
|
||||
@ -94,6 +99,7 @@ public class Parameter extends ModelElement {
|
||||
return ( mappingTarget ? "@MappingTarget " : "" )
|
||||
+ ( targetType ? "@TargetType " : "" )
|
||||
+ ( mappingContext ? "@Context " : "" )
|
||||
+ ( targetPropertyName ? "@TargetPropertyName " : "" )
|
||||
+ "%s " + name;
|
||||
}
|
||||
|
||||
@ -110,6 +116,10 @@ public class Parameter extends ModelElement {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
public boolean isTargetPropertyName() {
|
||||
return targetPropertyName;
|
||||
}
|
||||
|
||||
public boolean isVarArgs() {
|
||||
return varArgs;
|
||||
}
|
||||
@ -154,6 +164,7 @@ public class Parameter extends ModelElement {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
}
|
||||
@ -195,8 +206,15 @@ public class Parameter extends ModelElement {
|
||||
return parameters.stream().filter( Parameter::isTargetType ).findAny().orElse( null );
|
||||
}
|
||||
|
||||
public static Parameter getTargetPropertyNameParameter(List<Parameter> parameters) {
|
||||
return parameters.stream().filter( Parameter::isTargetPropertyName ).findAny().orElse( null );
|
||||
}
|
||||
|
||||
private static boolean isSourceParameter( Parameter parameter ) {
|
||||
return !parameter.isMappingTarget() && !parameter.isTargetType() && !parameter.isMappingContext();
|
||||
return !parameter.isMappingTarget() &&
|
||||
!parameter.isTargetType() &&
|
||||
!parameter.isMappingContext() &&
|
||||
!parameter.isTargetPropertyName();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,15 +22,17 @@ public class ParameterBinding {
|
||||
private final boolean targetType;
|
||||
private final boolean mappingTarget;
|
||||
private final boolean mappingContext;
|
||||
private final boolean targetPropertyName;
|
||||
private final SourceRHS sourceRHS;
|
||||
|
||||
private ParameterBinding(Type parameterType, String variableName, boolean mappingTarget, boolean targetType,
|
||||
boolean mappingContext, SourceRHS sourceRHS) {
|
||||
boolean mappingContext, boolean targetPropertyName, SourceRHS sourceRHS) {
|
||||
this.type = parameterType;
|
||||
this.variableName = variableName;
|
||||
this.targetType = targetType;
|
||||
this.mappingTarget = mappingTarget;
|
||||
this.mappingContext = mappingContext;
|
||||
this.targetPropertyName = targetPropertyName;
|
||||
this.sourceRHS = sourceRHS;
|
||||
}
|
||||
|
||||
@ -62,6 +64,13 @@ public class ParameterBinding {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true}, if the parameter being bound is a {@code @TargetPropertyName} parameter.
|
||||
*/
|
||||
public boolean isTargetPropertyName() {
|
||||
return targetPropertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type of the parameter that is bound
|
||||
*/
|
||||
@ -99,6 +108,7 @@ public class ParameterBinding {
|
||||
parameter.isMappingTarget(),
|
||||
parameter.isTargetType(),
|
||||
parameter.isMappingContext(),
|
||||
parameter.isTargetPropertyName(),
|
||||
null
|
||||
);
|
||||
}
|
||||
@ -118,6 +128,7 @@ public class ParameterBinding {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
@ -127,7 +138,14 @@ public class ParameterBinding {
|
||||
* @return a parameter binding representing a target type parameter
|
||||
*/
|
||||
public static ParameterBinding forTargetTypeBinding(Type classTypeOf) {
|
||||
return new ParameterBinding( classTypeOf, null, false, true, false, null );
|
||||
return new ParameterBinding( classTypeOf, null, false, true, false, false, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a parameter binding representing a target property name parameter
|
||||
*/
|
||||
public static ParameterBinding forTargetPropertyNameBinding(Type classTypeOf) {
|
||||
return new ParameterBinding( classTypeOf, null, false, false, false, true, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,7 +153,7 @@ public class ParameterBinding {
|
||||
* @return a parameter binding representing a mapping target parameter
|
||||
*/
|
||||
public static ParameterBinding forMappingTargetBinding(Type resultType) {
|
||||
return new ParameterBinding( resultType, null, true, false, false, null );
|
||||
return new ParameterBinding( resultType, null, true, false, false, false, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,10 +161,10 @@ public class ParameterBinding {
|
||||
* @return a parameter binding representing a mapping source type
|
||||
*/
|
||||
public static ParameterBinding forSourceTypeBinding(Type sourceType) {
|
||||
return new ParameterBinding( sourceType, null, false, false, false, null );
|
||||
return new ParameterBinding( sourceType, null, false, false, false, false, null );
|
||||
}
|
||||
|
||||
public static ParameterBinding fromSourceRHS(SourceRHS sourceRHS) {
|
||||
return new ParameterBinding( sourceRHS.getSourceType(), null, false, false, false, sourceRHS );
|
||||
return new ParameterBinding( sourceRHS.getSourceType(), null, false, false, false, false, sourceRHS );
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ public class SourceMethod implements Method {
|
||||
private final List<Parameter> parameters;
|
||||
private final Parameter mappingTargetParameter;
|
||||
private final Parameter targetTypeParameter;
|
||||
private final Parameter targetPropertyNameParameter;
|
||||
private final boolean isObjectFactory;
|
||||
private final boolean isPresenceCheck;
|
||||
private final Type returnType;
|
||||
@ -248,6 +249,7 @@ public class SourceMethod implements Method {
|
||||
|
||||
this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
|
||||
this.targetTypeParameter = Parameter.getTargetTypeParameter( parameters );
|
||||
this.targetPropertyNameParameter = Parameter.getTargetPropertyNameParameter( parameters );
|
||||
this.hasObjectFactoryAnnotation = ObjectFactoryGem.instanceOn( executable ) != null;
|
||||
this.isObjectFactory = determineIfIsObjectFactory();
|
||||
this.isPresenceCheck = determineIfIsPresenceCheck();
|
||||
@ -263,8 +265,9 @@ public class SourceMethod implements Method {
|
||||
private boolean determineIfIsObjectFactory() {
|
||||
boolean hasNoSourceParameters = getSourceParameters().isEmpty();
|
||||
boolean hasNoMappingTargetParam = getMappingTargetParameter() == null;
|
||||
boolean hasNoTargetPropertyNameParam = getTargetPropertyNameParameter() == null;
|
||||
return !isLifecycleCallbackMethod() && !returnType.isVoid()
|
||||
&& hasNoMappingTargetParam
|
||||
&& hasNoMappingTargetParam && hasNoTargetPropertyNameParam
|
||||
&& ( hasObjectFactoryAnnotation || hasNoSourceParameters );
|
||||
}
|
||||
|
||||
@ -379,6 +382,10 @@ public class SourceMethod implements Method {
|
||||
return targetTypeParameter;
|
||||
}
|
||||
|
||||
public Parameter getTargetPropertyNameParameter() {
|
||||
return targetPropertyNameParameter;
|
||||
}
|
||||
|
||||
public boolean isIterableMapping() {
|
||||
if ( isIterableMapping == null ) {
|
||||
isIterableMapping = getSourceParameters().size() == 1
|
||||
|
@ -96,7 +96,7 @@ public class TypeSelector implements MethodSelector {
|
||||
availableParams.addAll( ParameterBinding.fromParameters( method.getParameters() ) );
|
||||
}
|
||||
|
||||
addMappingTargetAndTargetTypeBindings( availableParams, targetType );
|
||||
addTargetRelevantBindings( availableParams, targetType );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
@ -116,7 +116,7 @@ public class TypeSelector implements MethodSelector {
|
||||
}
|
||||
}
|
||||
|
||||
addMappingTargetAndTargetTypeBindings( availableParams, targetType );
|
||||
addTargetRelevantBindings( availableParams, targetType );
|
||||
|
||||
return availableParams;
|
||||
}
|
||||
@ -127,9 +127,10 @@ public class TypeSelector implements MethodSelector {
|
||||
* @param availableParams Already available params, new entries will be added to this list
|
||||
* @param targetType Target type
|
||||
*/
|
||||
private void addMappingTargetAndTargetTypeBindings(List<ParameterBinding> availableParams, Type targetType) {
|
||||
private void addTargetRelevantBindings(List<ParameterBinding> availableParams, Type targetType) {
|
||||
boolean mappingTargetAvailable = false;
|
||||
boolean targetTypeAvailable = false;
|
||||
boolean targetPropertyNameAvailable = false;
|
||||
|
||||
// search available parameter bindings if mapping-target and/or target-type is available
|
||||
for ( ParameterBinding pb : availableParams ) {
|
||||
@ -139,6 +140,9 @@ public class TypeSelector implements MethodSelector {
|
||||
else if ( pb.isTargetType() ) {
|
||||
targetTypeAvailable = true;
|
||||
}
|
||||
else if ( pb.isTargetPropertyName() ) {
|
||||
targetPropertyNameAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mappingTargetAvailable ) {
|
||||
@ -147,6 +151,9 @@ public class TypeSelector implements MethodSelector {
|
||||
if ( !targetTypeAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetTypeBinding( typeFactory.classTypeOf( targetType ) ) );
|
||||
}
|
||||
if ( !targetPropertyNameAvailable ) {
|
||||
availableParams.add( ParameterBinding.forTargetPropertyNameBinding( typeFactory.getType( String.class ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Method> SelectedMethod<T> getMatchingParameterBinding(Type returnType,
|
||||
@ -301,7 +308,8 @@ public class TypeSelector implements MethodSelector {
|
||||
for ( ParameterBinding candidate : candidateParameters ) {
|
||||
if ( parameter.isTargetType() == candidate.isTargetType()
|
||||
&& parameter.isMappingTarget() == candidate.isMappingTarget()
|
||||
&& parameter.isMappingContext() == candidate.isMappingContext() ) {
|
||||
&& parameter.isMappingContext() == candidate.isMappingContext()
|
||||
&& parameter.isTargetPropertyName() == candidate.isTargetPropertyName()) {
|
||||
result.add( candidate );
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,8 @@
|
||||
<#if ext.targetBeanName??>${ext.targetBeanName}<#else>${param.variableName}</#if><#if ext.targetReadAccessorName??>.${ext.targetReadAccessorName}</#if><#t>
|
||||
<#elseif param.mappingContext>
|
||||
${param.variableName}<#t>
|
||||
<#elseif param.targetPropertyName>
|
||||
"${ext.targetPropertyName}"<#t>
|
||||
<#elseif param.sourceRHS??>
|
||||
<@_assignment assignmentToUse=param.sourceRHS/><#t>
|
||||
<#elseif assignment??>
|
||||
@ -66,5 +68,6 @@
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=singleSourceParameterType/>
|
||||
</#macro>
|
@ -7,4 +7,5 @@
|
||||
-->
|
||||
<#-- @ftlvariable name="" type="org.mapstruct.ap.internal.model.MethodReferencePresenceCheck" -->
|
||||
<@includeModel object=methodReference
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
@ -11,5 +11,6 @@
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=targetReadAccessorName
|
||||
targetWriteAccessorName=targetWriteAccessorName
|
||||
targetPropertyName=name
|
||||
targetType=targetType
|
||||
defaultValueAssignment=defaultValueAssignment />
|
@ -14,6 +14,7 @@ ${openExpression}<@_assignment/>${closeExpression}
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
||||
</#macro>
|
||||
</@compress>
|
||||
|
@ -34,5 +34,6 @@
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
||||
</#macro>
|
||||
|
@ -25,5 +25,6 @@
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
||||
</#macro>
|
@ -13,5 +13,6 @@ return <@_assignment/>;
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
||||
</#macro>
|
||||
|
@ -16,6 +16,7 @@
|
||||
<#macro handleSourceReferenceNullCheck>
|
||||
<#if sourcePresenceCheckerReference??>
|
||||
if ( <@includeModel object=sourcePresenceCheckerReference
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/> ) {
|
||||
<#nested>
|
||||
}
|
||||
@ -58,7 +59,8 @@
|
||||
-->
|
||||
<#macro handleLocalVarNullCheck needs_explicit_local_var>
|
||||
<#if sourcePresenceCheckerReference??>
|
||||
if ( <@includeModel object=sourcePresenceCheckerReference /> ) {
|
||||
if ( <@includeModel object=sourcePresenceCheckerReference
|
||||
targetPropertyName=ext.targetPropertyName/> ) {
|
||||
<#if needs_explicit_local_var>
|
||||
<@includeModel object=nullCheckLocalVarType/> ${nullCheckLocalVarName} = <@lib.handleAssignment/>;
|
||||
<#nested>
|
||||
@ -113,6 +115,7 @@ Performs a standard assignment.
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType/>
|
||||
</#macro>
|
||||
<#--
|
||||
@ -124,6 +127,7 @@ Performs a default assignment with a default value.
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
targetReadAccessorName=ext.targetReadAccessorName
|
||||
targetWriteAccessorName=ext.targetWriteAccessorName
|
||||
targetPropertyName=ext.targetPropertyName
|
||||
targetType=ext.targetType
|
||||
defaultValue=ext.defaultValue/>
|
||||
</#macro>
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
/**
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
public class Address implements DomainModel {
|
||||
private String street;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
/**
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
public class AddressDto implements DomainModel {
|
||||
private final String street;
|
||||
|
||||
public AddressDto(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@Mapper
|
||||
public interface ConditionalMethodForCollectionMapperWithTargetPropertyName {
|
||||
|
||||
ConditionalMethodForCollectionMapperWithTargetPropertyName INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodForCollectionMapperWithTargetPropertyName.class );
|
||||
|
||||
Employee map(EmployeeDto employee);
|
||||
|
||||
@Condition
|
||||
default <T> boolean isNotEmpty(Collection<T> collection, @TargetPropertyName String propName) {
|
||||
if ( "addresses".equalsIgnoreCase( propName ) ) {
|
||||
return false;
|
||||
}
|
||||
return collection != null && !collection.isEmpty();
|
||||
}
|
||||
|
||||
@Condition
|
||||
default boolean isNotBlank(String value, @TargetPropertyName String propName) {
|
||||
if ( propName.equalsIgnoreCase( "lastName" ) ) {
|
||||
return false;
|
||||
}
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@Mapper
|
||||
public interface ConditionalMethodInMapperWithAllExceptTarget {
|
||||
|
||||
ConditionalMethodInMapperWithAllExceptTarget INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodInMapperWithAllExceptTarget.class );
|
||||
|
||||
class PresenceUtils {
|
||||
Set<String> visited = new LinkedHashSet<>();
|
||||
Set<String> visitedSources = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
Employee map(EmployeeDto employee, @Context PresenceUtils utils);
|
||||
|
||||
@Condition
|
||||
default boolean isNotBlank(String value,
|
||||
DomainModel source,
|
||||
@TargetPropertyName 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,52 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@Mapper
|
||||
public interface ConditionalMethodInMapperWithAllOptions {
|
||||
|
||||
ConditionalMethodInMapperWithAllOptions INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodInMapperWithAllOptions.class );
|
||||
|
||||
class PresenceUtils {
|
||||
Set<String> visited = new LinkedHashSet<>();
|
||||
Set<String> visitedSources = new LinkedHashSet<>();
|
||||
Set<String> visitedTargets = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
void map(EmployeeDto employeeDto,
|
||||
@MappingTarget Employee employee,
|
||||
@Context PresenceUtils utils);
|
||||
|
||||
@Condition
|
||||
default boolean isNotBlank(String value,
|
||||
DomainModel source,
|
||||
@MappingTarget DomainModel target,
|
||||
@TargetPropertyName String propName,
|
||||
@Context PresenceUtils utils) {
|
||||
utils.visited.add( propName );
|
||||
utils.visitedSources.add( source.getClass().getSimpleName() );
|
||||
utils.visitedTargets.add( target.getClass().getSimpleName() );
|
||||
if ( propName.equalsIgnoreCase( "lastName" ) ) {
|
||||
return false;
|
||||
}
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@Mapper
|
||||
public interface ConditionalMethodInMapperWithTargetPropertyName {
|
||||
|
||||
ConditionalMethodInMapperWithTargetPropertyName INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodInMapperWithTargetPropertyName.class );
|
||||
|
||||
Employee map(EmployeeDto employee);
|
||||
|
||||
@Condition
|
||||
default boolean isNotBlank(String value, @TargetPropertyName String propName) {
|
||||
if ( propName.equalsIgnoreCase( "lastName" ) ) {
|
||||
return false;
|
||||
}
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
||||
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@Mapper(uses = ConditionalMethodInUsesMapperWithTargetPropertyName.PresenceUtils.class)
|
||||
public interface ConditionalMethodInUsesMapperWithTargetPropertyName {
|
||||
|
||||
ConditionalMethodInUsesMapperWithTargetPropertyName INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodInUsesMapperWithTargetPropertyName.class );
|
||||
|
||||
Employee map(EmployeeDto employee);
|
||||
|
||||
class PresenceUtils {
|
||||
|
||||
@Condition
|
||||
public boolean isNotBlank(String value, @TargetPropertyName String propName) {
|
||||
if ( propName.equalsIgnoreCase( "lastName" ) ) {
|
||||
return false;
|
||||
}
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.BeforeMapping;
|
||||
import org.mapstruct.Condition;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.TargetPropertyName;
|
||||
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č
|
||||
*/
|
||||
@Mapper
|
||||
public interface ConditionalMethodWithTargetPropertyNameInContextMapper {
|
||||
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper INSTANCE
|
||||
= Mappers.getMapper( ConditionalMethodWithTargetPropertyNameInContextMapper.class );
|
||||
|
||||
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, @TargetPropertyName String propName) {
|
||||
visited.add( propName );
|
||||
return value != null && !value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
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(@TargetPropertyName String propName) {
|
||||
visited.add( propName );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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 void after(@Context PresenceUtilsAllPropsWithSource utils) {
|
||||
utils.path.pollLast();
|
||||
}
|
||||
|
||||
class PresenceUtilsAllPropsWithSource {
|
||||
Deque<String> visitedSegments = new LinkedList<>();
|
||||
Deque<String> visited = new LinkedList<>();
|
||||
Deque<String> path = new LinkedList<>();
|
||||
|
||||
@Condition
|
||||
public boolean collect(@TargetPropertyName String propName) {
|
||||
visitedSegments.offerLast( propName );
|
||||
path.offerLast( propName );
|
||||
visited.offerLast( String.join( ".", path ) );
|
||||
path.pollLast();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
||||
|
||||
/**
|
||||
* Target Property Name test entities
|
||||
*
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
public interface DomainModel {
|
||||
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.conditional.targetpropertyname;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
public class Employee implements DomainModel {
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String title;
|
||||
private String country;
|
||||
private boolean active;
|
||||
private int age;
|
||||
|
||||
private Employee boss;
|
||||
|
||||
private Address primaryAddress;
|
||||
|
||||
private List<Address> addresses;
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Employee getBoss() {
|
||||
return boss;
|
||||
}
|
||||
|
||||
public void setBoss(Employee boss) {
|
||||
this.boss = boss;
|
||||
}
|
||||
|
||||
public Address getPrimaryAddress() {
|
||||
return primaryAddress;
|
||||
}
|
||||
|
||||
public void setPrimaryAddress(Address primaryAddress) {
|
||||
this.primaryAddress = primaryAddress;
|
||||
}
|
||||
|
||||
public List<Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(List<Address> addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
public class EmployeeDto implements DomainModel {
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String title;
|
||||
private String country;
|
||||
private boolean active;
|
||||
private int age;
|
||||
|
||||
private EmployeeDto boss;
|
||||
|
||||
private AddressDto primaryAddress;
|
||||
private List<AddressDto> addresses;
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public EmployeeDto getBoss() {
|
||||
return boss;
|
||||
}
|
||||
|
||||
public void setBoss(EmployeeDto boss) {
|
||||
this.boss = boss;
|
||||
}
|
||||
|
||||
public AddressDto getPrimaryAddress() {
|
||||
return primaryAddress;
|
||||
}
|
||||
|
||||
public void setPrimaryAddress(AddressDto primaryAddress) {
|
||||
this.primaryAddress = primaryAddress;
|
||||
}
|
||||
|
||||
public List<AddressDto> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(List<AddressDto> addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
}
|
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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.targetpropertyname;
|
||||
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.runner.GeneratedSource;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
* @author Nikola Ivačič
|
||||
*/
|
||||
@IssueKey("2051")
|
||||
@WithClasses({
|
||||
Address.class,
|
||||
AddressDto.class,
|
||||
Employee.class,
|
||||
EmployeeDto.class,
|
||||
DomainModel.class
|
||||
})
|
||||
public class TargetPropertyNameTest {
|
||||
|
||||
@RegisterExtension
|
||||
final GeneratedSource generatedSource = new GeneratedSource();
|
||||
|
||||
@ProcessorTest
|
||||
@WithClasses({
|
||||
ConditionalMethodInMapperWithTargetPropertyName.class
|
||||
})
|
||||
public void conditionalMethodInMapperWithTargetPropertyName() {
|
||||
ConditionalMethodInMapperWithTargetPropertyName mapper
|
||||
= ConditionalMethodInMapperWithTargetPropertyName.INSTANCE;
|
||||
|
||||
EmployeeDto employeeDto = new EmployeeDto();
|
||||
employeeDto.setFirstName( " " );
|
||||
employeeDto.setLastName( "Testirovich" );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||
);
|
||||
|
||||
Employee employee = mapper.map( employeeDto );
|
||||
assertThat( employee.getLastName() ).isNull();
|
||||
assertThat( employee.getFirstName() ).isNull();
|
||||
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||
assertThat( employee.getAddresses() )
|
||||
.extracting( Address::getStreet )
|
||||
.containsExactly( "Testing St. 6" );
|
||||
}
|
||||
|
||||
@ProcessorTest
|
||||
@WithClasses({
|
||||
ConditionalMethodForCollectionMapperWithTargetPropertyName.class
|
||||
})
|
||||
public void conditionalMethodForCollectionMapperWithTargetPropertyName() {
|
||||
ConditionalMethodForCollectionMapperWithTargetPropertyName mapper
|
||||
= ConditionalMethodForCollectionMapperWithTargetPropertyName.INSTANCE;
|
||||
|
||||
EmployeeDto employeeDto = new EmployeeDto();
|
||||
employeeDto.setFirstName( " " );
|
||||
employeeDto.setLastName( "Testirovich" );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||
);
|
||||
|
||||
Employee employee = mapper.map( employeeDto );
|
||||
assertThat( employee.getLastName() ).isNull();
|
||||
assertThat( employee.getFirstName() ).isNull();
|
||||
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||
assertThat( employee.getAddresses() ).isNull();
|
||||
}
|
||||
|
||||
@ProcessorTest
|
||||
@WithClasses({
|
||||
ConditionalMethodInUsesMapperWithTargetPropertyName.class
|
||||
})
|
||||
public void conditionalMethodInUsesMapperWithTargetPropertyName() {
|
||||
ConditionalMethodInUsesMapperWithTargetPropertyName mapper
|
||||
= ConditionalMethodInUsesMapperWithTargetPropertyName.INSTANCE;
|
||||
|
||||
EmployeeDto employeeDto = new EmployeeDto();
|
||||
employeeDto.setFirstName( " " );
|
||||
employeeDto.setLastName( "Testirovich" );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
Collections.singletonList( new AddressDto( "Testing St. 6" ) )
|
||||
);
|
||||
|
||||
Employee employee = mapper.map( employeeDto );
|
||||
assertThat( employee.getLastName() ).isNull();
|
||||
assertThat( employee.getFirstName() ).isNull();
|
||||
assertThat( employee.getCountry() ).isEqualTo( "US" );
|
||||
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.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
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.visited )
|
||||
.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.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
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", "country", "street" );
|
||||
assertThat( utils.visitedSources ).containsExactlyInAnyOrder( "EmployeeDto", "AddressDto" );
|
||||
}
|
||||
|
||||
@ProcessorTest
|
||||
@WithClasses({
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper.class
|
||||
})
|
||||
public void conditionalMethodWithTargetPropertyNameInUsesContextMapper() {
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper mapper
|
||||
= ConditionalMethodWithTargetPropertyNameInContextMapper.INSTANCE;
|
||||
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtils utils =
|
||||
new ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtils();
|
||||
|
||||
EmployeeDto employeeDto = new EmployeeDto();
|
||||
employeeDto.setLastName( " " );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
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", "country", "street" );
|
||||
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtilsAllProps allPropsUtils =
|
||||
new ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtilsAllProps();
|
||||
|
||||
employeeDto = new EmployeeDto();
|
||||
employeeDto.setLastName( "Tester" );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setAddresses(
|
||||
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",
|
||||
"country",
|
||||
"active",
|
||||
"age",
|
||||
"boss",
|
||||
"primaryAddress",
|
||||
"addresses",
|
||||
"street"
|
||||
);
|
||||
|
||||
ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtilsAllPropsWithSource allPropsUtilsWithSource =
|
||||
new ConditionalMethodWithTargetPropertyNameInContextMapper.PresenceUtilsAllPropsWithSource();
|
||||
|
||||
EmployeeDto bossEmployeeDto = new EmployeeDto();
|
||||
bossEmployeeDto.setLastName( "Boss Tester" );
|
||||
bossEmployeeDto.setCountry( "US" );
|
||||
bossEmployeeDto.setAddresses( Collections.singletonList( new AddressDto(
|
||||
"Testing St. 10" ) ) );
|
||||
|
||||
employeeDto = new EmployeeDto();
|
||||
employeeDto.setLastName( "Tester" );
|
||||
employeeDto.setCountry( "US" );
|
||||
employeeDto.setBoss( bossEmployeeDto );
|
||||
employeeDto.setAddresses(
|
||||
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(
|
||||
"firstName",
|
||||
"lastName",
|
||||
"title",
|
||||
"country",
|
||||
"active",
|
||||
"age",
|
||||
"boss",
|
||||
"boss.firstName",
|
||||
"boss.lastName",
|
||||
"boss.title",
|
||||
"boss.country",
|
||||
"boss.active",
|
||||
"boss.age",
|
||||
"boss.boss",
|
||||
"boss.primaryAddress",
|
||||
"boss.addresses",
|
||||
"boss.addresses.street",
|
||||
"primaryAddress",
|
||||
"addresses",
|
||||
"addresses.street"
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user