mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#295 NullValueMapping for BeanMapping on mapping method level
This commit is contained in:
parent
77937259b5
commit
24dc73765f
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Advises the code generator to apply all the {@link Mapping}s from an inverse mapping method to the annotated method
|
||||
* as well. An inverse mapping method is a method which has the annotated method's source type as target type (return
|
||||
* type or indicated through a parameter annotated with {@link MappingTarget}) and the annotated method's target type as
|
||||
* source type.
|
||||
* <p>
|
||||
* Any mappings given on the annotated method itself are added to those mappings inherited from the inverse method. In
|
||||
* case of a conflict local mappings take precedence over inherited mappings.
|
||||
* <p>
|
||||
* If more than one matching inverse method exists, the name of the method to inherit the configuration from must be
|
||||
* specified via {@link #name()}
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Target( { ElementType.METHOD, ElementType.TYPE } )
|
||||
@Retention( RetentionPolicy.SOURCE )
|
||||
public @interface MapNullToDefault {
|
||||
|
||||
boolean value() default true;
|
||||
}
|
@ -40,6 +40,7 @@ import org.mapstruct.ap.model.source.Mapping;
|
||||
import org.mapstruct.ap.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.model.source.SourceReference;
|
||||
import org.mapstruct.ap.option.ReportingPolicy;
|
||||
import org.mapstruct.ap.prism.MapNullToDefaultPrism;
|
||||
import org.mapstruct.ap.prism.CollectionMappingStrategyPrism;
|
||||
import org.mapstruct.ap.util.Executables;
|
||||
import org.mapstruct.ap.util.MapperConfig;
|
||||
@ -58,6 +59,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
private final Map<String, List<PropertyMapping>> mappingsByParameter;
|
||||
private final List<PropertyMapping> constantMappings;
|
||||
private final MethodReference factoryMethod;
|
||||
private final boolean mapNullToDefault;
|
||||
|
||||
public static class Builder {
|
||||
|
||||
@ -97,8 +99,12 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
// report errors on unmapped properties
|
||||
reportErrorForUnmappedTargetPropertiesIfRequired();
|
||||
|
||||
// mapNullToDefault
|
||||
MapNullToDefaultPrism prism = MapNullToDefaultPrism.getInstanceOn( method.getExecutable() );
|
||||
boolean mapNullToDefault = ( prism != null ) && prism.value();
|
||||
|
||||
MethodReference factoryMethod = AssignmentFactory.createFactoryMethod( method.getReturnType(), ctx );
|
||||
return new BeanMappingMethod( method, propertyMappings, factoryMethod );
|
||||
return new BeanMappingMethod( method, propertyMappings, factoryMethod, mapNullToDefault );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -472,7 +478,8 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
|
||||
private BeanMappingMethod(SourceMethod method,
|
||||
List<PropertyMapping> propertyMappings,
|
||||
MethodReference factoryMethod) {
|
||||
MethodReference factoryMethod,
|
||||
boolean mapNullToDefault ) {
|
||||
super( method );
|
||||
this.propertyMappings = propertyMappings;
|
||||
|
||||
@ -491,6 +498,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
}
|
||||
}
|
||||
this.factoryMethod = factoryMethod;
|
||||
this.mapNullToDefault = mapNullToDefault;
|
||||
}
|
||||
|
||||
public List<PropertyMapping> getPropertyMappings() {
|
||||
@ -505,6 +513,10 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
return mappingsByParameter;
|
||||
}
|
||||
|
||||
public boolean isMapNullToDefault() {
|
||||
return mapNullToDefault;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Type> getImportTypes() {
|
||||
Set<Type> types = super.getImportTypes();
|
||||
|
@ -27,6 +27,7 @@ import org.mapstruct.DecoratedWith;
|
||||
import org.mapstruct.InheritInverseConfiguration;
|
||||
import org.mapstruct.IterableMapping;
|
||||
import org.mapstruct.MapMapping;
|
||||
import org.mapstruct.MapNullToDefault;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MapperConfig;
|
||||
import org.mapstruct.Mapping;
|
||||
@ -52,6 +53,7 @@ import org.mapstruct.TargetType;
|
||||
@GeneratePrism(value = MapperConfig.class, publicAccess = true),
|
||||
@GeneratePrism(value = InheritInverseConfiguration.class, publicAccess = true),
|
||||
@GeneratePrism( value = Qualifier.class, publicAccess = true ),
|
||||
@GeneratePrism( value = MapNullToDefault.class, publicAccess = true ),
|
||||
|
||||
// external types
|
||||
@GeneratePrism(value = XmlElementDecl.class, publicAccess = true)
|
||||
|
@ -20,9 +20,11 @@
|
||||
-->
|
||||
@Override
|
||||
<#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) <@throws/> {
|
||||
<#if !mapNullToDefault>
|
||||
if ( <#list sourceParametersExcludingPrimitives as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && </#if></#list> ) {
|
||||
return<#if returnType.name != "void"> null</#if>;
|
||||
}
|
||||
</#if>
|
||||
|
||||
<#if !existingInstanceMapping><@includeModel object=resultType/> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod targetType=resultType raw=true/><#else>new <@includeModel object=resultType/>()</#if>;</#if>
|
||||
<#if (sourceParameters?size > 1)>
|
||||
@ -43,9 +45,11 @@
|
||||
</#if>
|
||||
</#list>
|
||||
<#else>
|
||||
<#if mapNullToDefault>if ( ${sourceParameters[0].name} != null ) {</#if>
|
||||
<#list propertyMappingsByParameter[sourceParameters[0].name] as propertyMapping>
|
||||
<@includeModel object=propertyMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
|
||||
</#list>
|
||||
<#if mapNullToDefault>}</#if>
|
||||
</#if>
|
||||
<#list constantMappings as constantMapping>
|
||||
<@includeModel object=constantMapping targetBeanName=resultName existingInstanceMapping=existingInstanceMapping/>
|
||||
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.mapnulltodefault;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MapNullToDefault;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.mapstruct.ap.test.mapnulltodefault.source.Car;
|
||||
import org.mapstruct.ap.test.mapnulltodefault.target.CarDto;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper(imports = UUID.class)
|
||||
public interface CarMapper {
|
||||
|
||||
CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
|
||||
|
||||
@MapNullToDefault
|
||||
@Mappings({
|
||||
@Mapping(target = "seatCount", source = "numberOfSeats"),
|
||||
@Mapping(target = "model", constant = "ModelT"),
|
||||
@Mapping(target = "catalogId", expression = "java( UUID.randomUUID().toString() )")
|
||||
})
|
||||
CarDto carToCarDto(Car car);
|
||||
|
||||
@MapNullToDefault
|
||||
@Mappings({
|
||||
@Mapping(target = "seatCount", source = "car.numberOfSeats"),
|
||||
@Mapping(target = "model", source = "model"), // TODO, should not be needed, must be made based on name only
|
||||
@Mapping(target = "catalogId", expression = "java( UUID.randomUUID().toString() )")
|
||||
})
|
||||
CarDto carToCarDto(Car car, String model);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.mapnulltodefault;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.test.mapnulltodefault.source.Car;
|
||||
import org.mapstruct.ap.test.mapnulltodefault.target.CarDto;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
@WithClasses({
|
||||
Car.class,
|
||||
CarDto.class,
|
||||
CarMapper.class
|
||||
})
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class CarMapperTest {
|
||||
|
||||
@Test
|
||||
public void shouldProvideMapperInstance() throws Exception {
|
||||
assertThat( CarMapper.INSTANCE ).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMapExpressionAndConstantRegardlessNullArg() {
|
||||
//given
|
||||
Car car = new Car( "Morris", 2 );
|
||||
|
||||
//when
|
||||
CarDto carDto1 = CarMapper.INSTANCE.carToCarDto( car );
|
||||
|
||||
//then
|
||||
assertThat( carDto1 ).isNotNull();
|
||||
assertThat( carDto1.getMake() ).isEqualTo( car.getMake() );
|
||||
assertThat( carDto1.getSeatCount() ).isEqualTo( car.getNumberOfSeats() );
|
||||
assertThat( carDto1.getModel() ).isEqualTo( "ModelT" );
|
||||
assertThat( carDto1.getCatalogId() ).isNotEmpty();
|
||||
|
||||
//when
|
||||
CarDto carDto2 = CarMapper.INSTANCE.carToCarDto( null );
|
||||
|
||||
//then
|
||||
assertThat( carDto2 ).isNotNull();
|
||||
assertThat( carDto2.getMake() ).isNull();
|
||||
assertThat( carDto2.getSeatCount() ).isEqualTo( 0 );
|
||||
assertThat( carDto2.getModel() ).isEqualTo( "ModelT" );
|
||||
assertThat( carDto2.getCatalogId() ).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMapExpressionAndConstantRegardlessNullArgSeveralSources() {
|
||||
//given
|
||||
Car car = new Car( "Morris", 2 );
|
||||
|
||||
//when
|
||||
CarDto carDto1 = CarMapper.INSTANCE.carToCarDto( car, "ModelT" );
|
||||
|
||||
//then
|
||||
assertThat( carDto1 ).isNotNull();
|
||||
assertThat( carDto1.getMake() ).isEqualTo( car.getMake() );
|
||||
assertThat( carDto1.getSeatCount() ).isEqualTo( car.getNumberOfSeats() );
|
||||
assertThat( carDto1.getCatalogId() ).isNotEmpty();
|
||||
|
||||
//when
|
||||
CarDto carDto2 = CarMapper.INSTANCE.carToCarDto( null, "ModelT" );
|
||||
|
||||
//then
|
||||
assertThat( carDto2 ).isNotNull();
|
||||
assertThat( carDto2.getMake() ).isNull();
|
||||
assertThat( carDto2.getSeatCount() ).isEqualTo( 0 );
|
||||
assertThat( carDto2.getModel() ).isEqualTo( "ModelT" );
|
||||
assertThat( carDto2.getCatalogId() ).isNotEmpty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.mapnulltodefault.source;
|
||||
|
||||
|
||||
public class Car {
|
||||
|
||||
private String make;
|
||||
private int numberOfSeats;
|
||||
|
||||
|
||||
public Car() {
|
||||
}
|
||||
|
||||
public Car(String make, int numberOfSeats) {
|
||||
this.make = make;
|
||||
this.numberOfSeats = numberOfSeats;
|
||||
|
||||
}
|
||||
|
||||
public String getMake() {
|
||||
return make;
|
||||
}
|
||||
|
||||
public void setMake(String make) {
|
||||
this.make = make;
|
||||
}
|
||||
|
||||
public int getNumberOfSeats() {
|
||||
return numberOfSeats;
|
||||
}
|
||||
|
||||
public void setNumberOfSeats(int numberOfSeats) {
|
||||
this.numberOfSeats = numberOfSeats;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.mapnulltodefault.target;
|
||||
|
||||
public class CarDto {
|
||||
|
||||
private String make;
|
||||
private int seatCount;
|
||||
private String model;
|
||||
private String catalogId;
|
||||
|
||||
|
||||
public CarDto() {
|
||||
}
|
||||
|
||||
public CarDto(String make, int seatCount) {
|
||||
this.make = make;
|
||||
this.seatCount = seatCount;
|
||||
}
|
||||
|
||||
public String getMake() {
|
||||
return make;
|
||||
}
|
||||
|
||||
public void setMake(String make) {
|
||||
this.make = make;
|
||||
}
|
||||
|
||||
public int getSeatCount() {
|
||||
return seatCount;
|
||||
}
|
||||
|
||||
public void setSeatCount(int seatCount) {
|
||||
this.seatCount = seatCount;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel( String model ) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public String getCatalogId() {
|
||||
return catalogId;
|
||||
}
|
||||
|
||||
public void setCatalogId( String catalogId ) {
|
||||
this.catalogId = catalogId;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user