mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#669 rework into sourcepresencecheck SPI and nullvaluecheckstrategy
This commit is contained in:
parent
1af4441d2d
commit
b1f03689d9
@ -17,6 +17,7 @@ Remko Plantenga
|
|||||||
Samuel Wright
|
Samuel Wright
|
||||||
Sebastian Hasait
|
Sebastian Hasait
|
||||||
Sjaak Derksen
|
Sjaak Derksen
|
||||||
|
Sean Huang
|
||||||
Timo Eckhardt
|
Timo Eckhardt
|
||||||
Tomek Gubala
|
Tomek Gubala
|
||||||
Vincent Alexander Beelte
|
Vincent Alexander Beelte
|
||||||
|
@ -18,14 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks an interface or abstract class as a mapper and activates the generation of a implementation of that type via
|
* Marks an interface or abstract class as a mapper and activates the generation of a implementation of that type via
|
||||||
@ -152,10 +151,11 @@ public @interface Mapper {
|
|||||||
MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.EXPLICIT;
|
MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.EXPLICIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decide how to do presence check, such as checking null or calling hasX method, before mapping.
|
* Determines when to include a null check on the source property value of a bean mapping.
|
||||||
|
*
|
||||||
* Can be overridden by the one on {@link MapperConfig} or {@link Mapping}.
|
* Can be overridden by the one on {@link MapperConfig} or {@link Mapping}.
|
||||||
*
|
*
|
||||||
* @return strategy about how to do null or presence check
|
* @return strategy how to do null checking
|
||||||
*/
|
*/
|
||||||
SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL_INLINE;
|
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks a class or interface as configuration source for generated mappers. This allows to share common configurations
|
* Marks a class or interface as configuration source for generated mappers. This allows to share common configurations
|
||||||
@ -139,10 +138,11 @@ public @interface MapperConfig {
|
|||||||
default MappingInheritanceStrategy.EXPLICIT;
|
default MappingInheritanceStrategy.EXPLICIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decide how to do presence check, such as checking null or calling hasXXX method, before mapping.
|
* Determines when to include a null check on the source property value of a bean mapping.
|
||||||
|
*
|
||||||
* Can be overridden by the one on {@link Mapper} or {@link Mapping}.
|
* Can be overridden by the one on {@link Mapper} or {@link Mapping}.
|
||||||
*
|
*
|
||||||
* @return strategy about how to do null or presence check
|
* @return strategy how to do null checking
|
||||||
*/
|
*/
|
||||||
SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL_INLINE;
|
NullValueCheckStrategy nullValueCheckStrategy() default ON_IMPLICIT_CONVERSION;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strategy for dealing with null source values.
|
||||||
|
*
|
||||||
|
* <b>Note:</b> This strategy is not in effect when the a specific source presence check method is defined
|
||||||
|
* in the service provider interface (SPI).
|
||||||
|
*
|
||||||
|
* @author Sean Huang
|
||||||
|
*/
|
||||||
|
public enum NullValueCheckStrategy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This option includes a null check. When:
|
||||||
|
* <p>
|
||||||
|
* <ol>
|
||||||
|
* <li>a source value is directly assigned to a target</li>
|
||||||
|
* <li>a source value assigned to a target by calling a type conversion on the target first</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE:</b> mapping methods (generated or hand written) are excluded from this null check. They are intended to
|
||||||
|
* handle a null source value as 'valid' input.
|
||||||
|
*
|
||||||
|
*//**
|
||||||
|
* This option includes a null check. When:
|
||||||
|
* <p>
|
||||||
|
* <ol>
|
||||||
|
* <li>a source value is directly assigned to a target</li>
|
||||||
|
* <li>a source value assigned to a target by calling a type conversion on the target first</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE:</b> mapping methods (generated or hand written) are excluded from this null check. They are intended to
|
||||||
|
* handle a null source value as 'valid' input.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ON_IMPLICIT_CONVERSION,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This option always includes a null check.
|
||||||
|
*/
|
||||||
|
ALLWAYS,
|
||||||
|
|
||||||
|
}
|
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Repeatable;
|
import java.lang.annotation.Repeatable;
|
||||||
@ -193,12 +191,4 @@ public @interface Mapping {
|
|||||||
* @return Default value to set in case the source property is {@code null}.
|
* @return Default value to set in case the source property is {@code null}.
|
||||||
*/
|
*/
|
||||||
String defaultValue() default "";
|
String defaultValue() default "";
|
||||||
|
|
||||||
/**
|
|
||||||
* Decide whether we should check null or hasX method before mapping.
|
|
||||||
* The value on {@link Mapper} can override this one.
|
|
||||||
*
|
|
||||||
* @return strategy about how to do null or has value check
|
|
||||||
*/
|
|
||||||
SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL;
|
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct;
|
||||||
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.annotation.ElementType;
|
import java.lang.annotation.ElementType;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@ -192,12 +190,4 @@ public @interface Mapping {
|
|||||||
* @return Default value to set in case the source property is {@code null}.
|
* @return Default value to set in case the source property is {@code null}.
|
||||||
*/
|
*/
|
||||||
String defaultValue() default "";
|
String defaultValue() default "";
|
||||||
|
|
||||||
/**
|
|
||||||
* Decide how to do presence check, such as checking null or calling hasXXX method, before mapping.
|
|
||||||
* If it is set to default, it can be overridden by the one on {@link MapperConfig} or {@link Mapper}.
|
|
||||||
*
|
|
||||||
* @return strategy about how to do null or presence check
|
|
||||||
*/
|
|
||||||
SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL_INLINE;
|
|
||||||
}
|
}
|
||||||
|
@ -370,7 +370,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
while ( targetPropertiesIterator.hasNext() ) {
|
while ( targetPropertiesIterator.hasNext() ) {
|
||||||
|
|
||||||
Entry<String, ExecutableElement> targetProperty = targetPropertiesIterator.next();
|
Entry<String, ExecutableElement> targetProperty = targetPropertiesIterator.next();
|
||||||
String propertyName = targetProperty.getKey();
|
String targetPropertyName = targetProperty.getKey();
|
||||||
|
|
||||||
PropertyMapping propertyMapping = null;
|
PropertyMapping propertyMapping = null;
|
||||||
|
|
||||||
@ -387,10 +387,10 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
PropertyMapping newPropertyMapping = null;
|
PropertyMapping newPropertyMapping = null;
|
||||||
|
|
||||||
ExecutableElement sourceReadAccessor =
|
ExecutableElement sourceReadAccessor =
|
||||||
sourceParameter.getType().getPropertyReadAccessors().get( propertyName );
|
sourceParameter.getType().getPropertyReadAccessors().get( targetPropertyName );
|
||||||
|
|
||||||
ExecutableElement sourcePresenceChecker =
|
ExecutableElement sourcePresenceChecker =
|
||||||
sourceParameter.getType().getPropertyPresenceCheckers().get( propertyName );
|
sourceParameter.getType().getPropertyPresenceCheckers().get( targetPropertyName );
|
||||||
|
|
||||||
if ( sourceReadAccessor != null ) {
|
if ( sourceReadAccessor != null ) {
|
||||||
Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() );
|
Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() );
|
||||||
@ -408,8 +408,8 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
.mappingContext( ctx )
|
.mappingContext( ctx )
|
||||||
.sourceMethod( method )
|
.sourceMethod( method )
|
||||||
.targetWriteAccessor( targetProperty.getValue() )
|
.targetWriteAccessor( targetProperty.getValue() )
|
||||||
.targetReadAccessor( getTargetPropertyReadAccessor( propertyName ) )
|
.targetReadAccessor( getTargetPropertyReadAccessor( targetPropertyName ) )
|
||||||
.targetPropertyName( propertyName )
|
.targetPropertyName( targetPropertyName )
|
||||||
.sourceReference( sourceRef )
|
.sourceReference( sourceRef )
|
||||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
||||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
||||||
@ -426,7 +426,7 @@ public class BeanMappingMethod extends MappingMethod {
|
|||||||
ctx.getMessager().printMessage(
|
ctx.getMessager().printMessage(
|
||||||
method.getExecutable(),
|
method.getExecutable(),
|
||||||
Message.BEANMAPPING_SEVERAL_POSSIBLE_SOURCES,
|
Message.BEANMAPPING_SEVERAL_POSSIBLE_SOURCES,
|
||||||
propertyName
|
targetPropertyName
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentTy
|
|||||||
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.MAPPED_TYPE_CONVERTED;
|
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.MAPPED_TYPE_CONVERTED;
|
||||||
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED;
|
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED;
|
||||||
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED_MAPPED;
|
import static org.mapstruct.ap.internal.model.assignment.Assignment.AssignmentType.TYPE_CONVERTED_MAPPED;
|
||||||
|
import static org.mapstruct.ap.internal.prism.NullValueCheckStrategy.ALLWAYS;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -52,6 +53,7 @@ import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
|||||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||||
import org.mapstruct.ap.internal.model.source.SourceReference;
|
import org.mapstruct.ap.internal.model.source.SourceReference;
|
||||||
import org.mapstruct.ap.internal.model.source.SourceReference.PropertyEntry;
|
import org.mapstruct.ap.internal.model.source.SourceReference.PropertyEntry;
|
||||||
|
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||||
import org.mapstruct.ap.internal.util.Executables;
|
import org.mapstruct.ap.internal.util.Executables;
|
||||||
import org.mapstruct.ap.internal.util.MapperConfiguration;
|
import org.mapstruct.ap.internal.util.MapperConfiguration;
|
||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
@ -235,23 +237,14 @@ public class PropertyMapping extends ModelElement {
|
|||||||
|
|
||||||
if ( assignment != null ) {
|
if ( assignment != null ) {
|
||||||
if ( targetType.isCollectionOrMapType() ) {
|
if ( targetType.isCollectionOrMapType() ) {
|
||||||
assignment = assignCollection( targetType, targetWriteAccessorType, assignment );
|
assignment = assignToCollection( targetType, targetWriteAccessorType, assignment );
|
||||||
}
|
}
|
||||||
else if ( targetType.isArrayType() && sourceType.isArrayType() && assignment.getType() == DIRECT ) {
|
else if ( targetType.isArrayType() && sourceType.isArrayType() && assignment.getType() == DIRECT ) {
|
||||||
Type arrayType = ctx.getTypeFactory().getType( Arrays.class );
|
assignment = assignToArray( targetType, assignment );
|
||||||
assignment = new ArrayCopyWrapper(
|
|
||||||
assignment,
|
|
||||||
targetPropertyName,
|
|
||||||
arrayType,
|
|
||||||
targetType,
|
|
||||||
existingVariableNames
|
|
||||||
);
|
|
||||||
assignment = new NullCheckWrapper( assignment );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assignment = assignObject( sourceType, targetType, targetWriteAccessorType, assignment );
|
assignment = assignToPlain( sourceType, targetType, targetWriteAccessorType, assignment );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ctx.getMessager().printMessage(
|
ctx.getMessager().printMessage(
|
||||||
@ -278,7 +271,9 @@ public class PropertyMapping extends ModelElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Assignment getDefaultValueAssignment() {
|
private Assignment getDefaultValueAssignment() {
|
||||||
if ( defaultValue != null && !getSourceType().isPrimitive() ) {
|
if ( defaultValue != null
|
||||||
|
&& ( !getSourceType().isPrimitive() || getSourcePresenceCheckerRef() != null) ) {
|
||||||
|
// cannot check on null source if source is primitive unless it has a presenche checker
|
||||||
PropertyMapping build = new ConstantMappingBuilder()
|
PropertyMapping build = new ConstantMappingBuilder()
|
||||||
.constantExpression( '"' + defaultValue + '"' )
|
.constantExpression( '"' + defaultValue + '"' )
|
||||||
.formattingParameters( formattingParameters )
|
.formattingParameters( formattingParameters )
|
||||||
@ -296,43 +291,80 @@ public class PropertyMapping extends ModelElement {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Assignment assignObject(Type sourceType, Type targetType, TargetWriteAccessorType targetAccessorType,
|
private Assignment assignToPlain(Type sourceType, Type targetType, TargetWriteAccessorType targetAccessorType,
|
||||||
Assignment rhs) {
|
Assignment rightHandSide) {
|
||||||
|
|
||||||
Assignment result = rhs;
|
Assignment result;
|
||||||
|
|
||||||
if ( targetAccessorType == TargetWriteAccessorType.SETTER ) {
|
if ( targetAccessorType == TargetWriteAccessorType.SETTER ) {
|
||||||
if ( result.isUpdateMethod() ) {
|
result = assignToPlainViaSetter( sourceType, targetType, rightHandSide );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = assignToPlainViaAdder( sourceType, rightHandSide );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Assignment assignToPlainViaSetter(Type sourceType, Type targetType, Assignment rightHandSide) {
|
||||||
|
|
||||||
|
Assignment result;
|
||||||
|
|
||||||
|
if ( rightHandSide.isUpdateMethod() ) {
|
||||||
if ( targetReadAccessor == null ) {
|
if ( targetReadAccessor == null ) {
|
||||||
ctx.getMessager().printMessage( method.getExecutable(),
|
ctx.getMessager().printMessage( method.getExecutable(),
|
||||||
Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE,
|
Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE,
|
||||||
targetPropertyName );
|
targetPropertyName );
|
||||||
}
|
}
|
||||||
Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
|
Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
|
||||||
result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod,
|
result = new UpdateWrapper( rightHandSide, method.getThrownTypes(), factoryMethod,
|
||||||
targetType );
|
targetType );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = new SetterWrapper( result, method.getThrownTypes() );
|
result = new SetterWrapper( rightHandSide, method.getThrownTypes() );
|
||||||
}
|
}
|
||||||
if ( !sourceType.isPrimitive()
|
|
||||||
&& !sourceReference.getPropertyEntries().isEmpty() ) { // parameter null taken care of by beanmapper
|
// if the sourceReference is the bean mapping method parameter itself, no null check is required
|
||||||
|
// since this is handled by the BeanMapping
|
||||||
|
if ( sourceReference.getPropertyEntries().isEmpty() ) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a null / presence checked when required
|
||||||
|
if ( sourceType.isPrimitive() ) {
|
||||||
|
if ( getSourcePresenceCheckerRef() != null ) {
|
||||||
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
if ( result.isUpdateMethod() ) {
|
if ( result.isUpdateMethod() ) {
|
||||||
result = new UpdateNullCheckWrapper( result );
|
result = new UpdateNullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
|
}
|
||||||
|
else if ( getSourcePresenceCheckerRef() != null ) {
|
||||||
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
|
}
|
||||||
|
else if ( ALLWAYS.equals( method.getMapperConfiguration().getNullValueCheckStrategy() ) ) {
|
||||||
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
}
|
||||||
else if ( result.getType() == TYPE_CONVERTED
|
else if ( result.getType() == TYPE_CONVERTED
|
||||||
|| result.getType() == TYPE_CONVERTED_MAPPED
|
|| result.getType() == TYPE_CONVERTED_MAPPED
|
||||||
|| result.getType() == MAPPED_TYPE_CONVERTED
|
|| result.getType() == MAPPED_TYPE_CONVERTED
|
||||||
|| ( result.getType() == DIRECT && targetType.isPrimitive() ) ) {
|
|| (result.getType() == DIRECT && targetType.isPrimitive()) ) {
|
||||||
// for primitive types null check is not possible at all, but a conversion needs
|
// for primitive types null check is not possible at all, but a conversion needs
|
||||||
// a null check.
|
// a null check.
|
||||||
result = new NullCheckWrapper( result );
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// TargetAccessorType must be ADDER
|
|
||||||
|
private Assignment assignToPlainViaAdder(Type sourceType, Assignment rightHandSide) {
|
||||||
|
|
||||||
|
Assignment result = rightHandSide;
|
||||||
|
|
||||||
if ( getSourceType().isCollectionType() ) {
|
if ( getSourceType().isCollectionType() ) {
|
||||||
result = new AdderWrapper(
|
result = new AdderWrapper(
|
||||||
result,
|
result,
|
||||||
@ -340,19 +372,17 @@ public class PropertyMapping extends ModelElement {
|
|||||||
getSourceRef(),
|
getSourceRef(),
|
||||||
sourceType
|
sourceType
|
||||||
);
|
);
|
||||||
result = new NullCheckWrapper( result );
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Possibly adding null to a target collection. So should be surrounded by an null check.
|
// Possibly adding null to a target collection. So should be surrounded by an null check.
|
||||||
result = new SetterWrapper( result, method.getThrownTypes() );
|
result = new SetterWrapper( result, method.getThrownTypes() );
|
||||||
result = new NullCheckWrapper( result );
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Assignment assignCollection(Type targetType,
|
private Assignment assignToCollection(Type targetType,
|
||||||
TargetWriteAccessorType targetAccessorType,
|
TargetWriteAccessorType targetAccessorType,
|
||||||
Assignment rhs) {
|
Assignment rhs) {
|
||||||
|
|
||||||
@ -419,15 +449,28 @@ public class PropertyMapping extends ModelElement {
|
|||||||
// for mapping methods (builtin / custom), the mapping method is responsible for the
|
// for mapping methods (builtin / custom), the mapping method is responsible for the
|
||||||
// null check. Typeconversions do not apply to collections and maps.
|
// null check. Typeconversions do not apply to collections and maps.
|
||||||
if ( result.getType() == DIRECT ) {
|
if ( result.getType() == DIRECT ) {
|
||||||
result = new NullCheckWrapper( result );
|
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
}
|
||||||
else if ( result.getType() == MAPPED && result.isUpdateMethod() ) {
|
else if ( result.getType() == MAPPED && result.isUpdateMethod() ) {
|
||||||
result = new UpdateNullCheckWrapper( result );
|
result = new UpdateNullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Assignment assignToArray(Type targetType, Assignment rightHandSide) {
|
||||||
|
|
||||||
|
Type arrayType = ctx.getTypeFactory().getType( Arrays.class );
|
||||||
|
Assignment assignment = new ArrayCopyWrapper(
|
||||||
|
rightHandSide,
|
||||||
|
targetPropertyName,
|
||||||
|
arrayType,
|
||||||
|
targetType,
|
||||||
|
existingVariableNames
|
||||||
|
);
|
||||||
|
return new NullCheckWrapper( assignment, getSourcePresenceCheckerRef() );
|
||||||
|
}
|
||||||
|
|
||||||
private Type getSourceType() {
|
private Type getSourceType() {
|
||||||
|
|
||||||
Parameter sourceParam = sourceReference.getParameter();
|
Parameter sourceParam = sourceReference.getParameter();
|
||||||
@ -514,6 +557,19 @@ public class PropertyMapping extends ModelElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSourcePresenceCheckerRef() {
|
||||||
|
String sourcePresenceChecker = null;
|
||||||
|
if ( !sourceReference.getPropertyEntries().isEmpty() ) {
|
||||||
|
Parameter sourceParam = sourceReference.getParameter();
|
||||||
|
PropertyEntry propertyEntry = first( sourceReference.getPropertyEntries() );
|
||||||
|
if ( propertyEntry.getPresenceChecker() != null ) {
|
||||||
|
sourcePresenceChecker = sourceParam.getName()
|
||||||
|
+ "." + propertyEntry.getPresenceChecker().getSimpleName() + "()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sourcePresenceChecker;
|
||||||
|
}
|
||||||
|
|
||||||
private Assignment forgeMapOrIterableMapping(Type sourceType, Type targetType, String sourceReference,
|
private Assignment forgeMapOrIterableMapping(Type sourceType, Type targetType, String sourceReference,
|
||||||
ExecutableElement element) {
|
ExecutableElement element) {
|
||||||
|
|
||||||
|
@ -25,7 +25,15 @@ package org.mapstruct.ap.internal.model.assignment;
|
|||||||
*/
|
*/
|
||||||
public class NullCheckWrapper extends AssignmentWrapper {
|
public class NullCheckWrapper extends AssignmentWrapper {
|
||||||
|
|
||||||
public NullCheckWrapper( Assignment decoratedAssignment ) {
|
private final String sourcePresenceChecker;
|
||||||
|
|
||||||
|
|
||||||
|
public NullCheckWrapper( Assignment decoratedAssignment, String sourcePresenceChecker ) {
|
||||||
super( decoratedAssignment );
|
super( decoratedAssignment );
|
||||||
|
this.sourcePresenceChecker = sourcePresenceChecker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSourcePresenceChecker() {
|
||||||
|
return sourcePresenceChecker;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,15 @@ package org.mapstruct.ap.internal.model.assignment;
|
|||||||
*/
|
*/
|
||||||
public class UpdateNullCheckWrapper extends AssignmentWrapper {
|
public class UpdateNullCheckWrapper extends AssignmentWrapper {
|
||||||
|
|
||||||
public UpdateNullCheckWrapper( Assignment decoratedAssignment ) {
|
private final String sourcePresenceChecker;
|
||||||
|
|
||||||
|
public UpdateNullCheckWrapper( Assignment decoratedAssignment, String sourcePresenceChecker ) {
|
||||||
super( decoratedAssignment );
|
super( decoratedAssignment );
|
||||||
|
this.sourcePresenceChecker = sourcePresenceChecker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSourcePresenceChecker() {
|
||||||
|
return sourcePresenceChecker;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ import org.mapstruct.ap.internal.model.common.TypeFactory;
|
|||||||
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
|
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
|
||||||
import org.mapstruct.ap.internal.prism.MappingPrism;
|
import org.mapstruct.ap.internal.prism.MappingPrism;
|
||||||
import org.mapstruct.ap.internal.prism.MappingsPrism;
|
import org.mapstruct.ap.internal.prism.MappingsPrism;
|
||||||
import org.mapstruct.ap.internal.prism.SourceValuePresenceCheckStrategy;
|
|
||||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
|
|
||||||
@ -62,9 +61,6 @@ public class Mapping {
|
|||||||
private final boolean isIgnored;
|
private final boolean isIgnored;
|
||||||
private final List<String> dependsOn;
|
private final List<String> dependsOn;
|
||||||
|
|
||||||
private final SourceValuePresenceCheckStrategy valuePresenceCheckStrategy;
|
|
||||||
private final boolean isSetValuePresenceCheckStrategy;
|
|
||||||
|
|
||||||
private final AnnotationMirror mirror;
|
private final AnnotationMirror mirror;
|
||||||
private final AnnotationValue sourceAnnotationValue;
|
private final AnnotationValue sourceAnnotationValue;
|
||||||
private final AnnotationValue targetAnnotationValue;
|
private final AnnotationValue targetAnnotationValue;
|
||||||
@ -142,7 +138,6 @@ public class Mapping {
|
|||||||
List<String> dependsOn =
|
List<String> dependsOn =
|
||||||
mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.<String>emptyList();
|
mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.<String>emptyList();
|
||||||
|
|
||||||
boolean isSetValuePresenceCheckStrategy = mappingPrism.values.sourceValuePresenceCheckStrategy() != null;
|
|
||||||
|
|
||||||
FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat );
|
FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat );
|
||||||
SelectionParameters selectionParams = new SelectionParameters(
|
SelectionParameters selectionParams = new SelectionParameters(
|
||||||
@ -163,9 +158,7 @@ public class Mapping {
|
|||||||
formattingParam,
|
formattingParam,
|
||||||
selectionParams,
|
selectionParams,
|
||||||
mappingPrism.values.dependsOn(),
|
mappingPrism.values.dependsOn(),
|
||||||
dependsOn,
|
dependsOn
|
||||||
SourceValuePresenceCheckStrategy.valueOf( mappingPrism.sourceValuePresenceCheckStrategy() ),
|
|
||||||
isSetValuePresenceCheckStrategy
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,9 +167,7 @@ public class Mapping {
|
|||||||
String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
||||||
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
||||||
FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
||||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn,
|
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn ) {
|
||||||
SourceValuePresenceCheckStrategy valuePresenceCheckStrategy,
|
|
||||||
boolean isSetValuePresenceCheckStrategy ) {
|
|
||||||
this.sourceName = sourceName;
|
this.sourceName = sourceName;
|
||||||
this.constant = constant;
|
this.constant = constant;
|
||||||
this.javaExpression = javaExpression;
|
this.javaExpression = javaExpression;
|
||||||
@ -190,8 +181,6 @@ public class Mapping {
|
|||||||
this.selectionParameters = selectionParameters;
|
this.selectionParameters = selectionParameters;
|
||||||
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
||||||
this.dependsOn = dependsOn;
|
this.dependsOn = dependsOn;
|
||||||
this.valuePresenceCheckStrategy = valuePresenceCheckStrategy;
|
|
||||||
this.isSetValuePresenceCheckStrategy = isSetValuePresenceCheckStrategy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element,
|
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element,
|
||||||
@ -292,14 +281,6 @@ public class Mapping {
|
|||||||
return dependsOn;
|
return dependsOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() {
|
|
||||||
return valuePresenceCheckStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSetSourceValuePresenceCheckStrategy() {
|
|
||||||
return isSetValuePresenceCheckStrategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
|
private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
|
||||||
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
|
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
|
||||||
return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name );
|
return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name );
|
||||||
@ -348,9 +329,7 @@ public class Mapping {
|
|||||||
formattingParameters,
|
formattingParameters,
|
||||||
selectionParameters,
|
selectionParameters,
|
||||||
dependsOnAnnotationValue,
|
dependsOnAnnotationValue,
|
||||||
Collections.<String>emptyList(),
|
Collections.<String>emptyList()
|
||||||
valuePresenceCheckStrategy,
|
|
||||||
isSetValuePresenceCheckStrategy
|
|
||||||
);
|
);
|
||||||
|
|
||||||
reverse.init( method, messager, typeFactory );
|
reverse.init( method, messager, typeFactory );
|
||||||
@ -377,9 +356,7 @@ public class Mapping {
|
|||||||
formattingParameters,
|
formattingParameters,
|
||||||
selectionParameters,
|
selectionParameters,
|
||||||
dependsOnAnnotationValue,
|
dependsOnAnnotationValue,
|
||||||
dependsOn,
|
dependsOn
|
||||||
valuePresenceCheckStrategy,
|
|
||||||
isSetValuePresenceCheckStrategy
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( sourceReference != null ) {
|
if ( sourceReference != null ) {
|
||||||
|
@ -16,19 +16,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.internal.prism;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Prism for the enum {@link org.mapstruct.SourceValuePresenceCheckStrategy}
|
||||||
|
*
|
||||||
* @author Sean Huang
|
* @author Sean Huang
|
||||||
*/
|
*/
|
||||||
public class MyObject {
|
public enum NullValueCheckStrategy {
|
||||||
@Override
|
|
||||||
public boolean equals(Object object) {
|
|
||||||
return this == object;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
ON_IMPLICIT_CONVERSION,
|
||||||
public int hashCode() {
|
ALLWAYS;
|
||||||
return super.hashCode();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,81 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2016 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.internal.services;
|
|
||||||
|
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple locator for SPI implementations.
|
|
||||||
*
|
|
||||||
* @author Christian Schuster
|
|
||||||
*/
|
|
||||||
public class Services {
|
|
||||||
|
|
||||||
private static final ConcurrentMap<Class<?>, Object> SERVICES = new ConcurrentHashMap<Class<?>, Object>();
|
|
||||||
|
|
||||||
private Services() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T get(Class<T> serviceType, T defaultValue) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T service = (T) SERVICES.get( serviceType );
|
|
||||||
|
|
||||||
if ( service == null ) {
|
|
||||||
service = loadAndCache( serviceType, defaultValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> T loadAndCache(Class<T> serviceType, T defaultValue) {
|
|
||||||
T service = find( serviceType );
|
|
||||||
if ( service == null ) {
|
|
||||||
service = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T cached = (T) SERVICES.putIfAbsent( serviceType, service );
|
|
||||||
if ( cached != null ) {
|
|
||||||
service = (T) cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> T find(Class<T> spi) {
|
|
||||||
T matchingImplementation = null;
|
|
||||||
|
|
||||||
for ( T implementation : ServiceLoader.load( spi, spi.getClassLoader() ) ) {
|
|
||||||
if ( matchingImplementation == null ) {
|
|
||||||
matchingImplementation = implementation;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalStateException(
|
|
||||||
"Multiple implementations have been found for the service provider interface "
|
|
||||||
+ spi.getCanonicalName() + ": " + matchingImplementation.getClass().getCanonicalName() + ", "
|
|
||||||
+ implementation.getClass().getCanonicalName() + "."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return matchingImplementation;
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,11 +35,10 @@ import javax.lang.model.type.TypeKind;
|
|||||||
import javax.lang.model.type.TypeMirror;
|
import javax.lang.model.type.TypeMirror;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.naming.DefaultAccessorNamingStrategy;
|
|
||||||
import org.mapstruct.ap.internal.prism.AfterMappingPrism;
|
import org.mapstruct.ap.internal.prism.AfterMappingPrism;
|
||||||
import org.mapstruct.ap.internal.prism.BeforeMappingPrism;
|
import org.mapstruct.ap.internal.prism.BeforeMappingPrism;
|
||||||
import org.mapstruct.ap.internal.services.Services;
|
|
||||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||||
|
import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy;
|
||||||
import org.mapstruct.ap.spi.MethodType;
|
import org.mapstruct.ap.spi.MethodType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,8 +62,7 @@ public class Executables {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = Services.get(
|
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = Services.get(
|
||||||
AccessorNamingStrategy.class,
|
AccessorNamingStrategy.class, new DefaultAccessorNamingStrategy()
|
||||||
new DefaultAccessorNamingStrategy()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
private Executables() {
|
private Executables() {
|
||||||
@ -98,8 +96,8 @@ public class Executables {
|
|||||||
return method.getModifiers().contains( Modifier.PUBLIC );
|
return method.getModifiers().contains( Modifier.PUBLIC );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) {
|
public static String getPropertyName(ExecutableElement getterOrPresenceCheckerOrSetterMethod) {
|
||||||
return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrHasserOrSetterMethod );
|
return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrPresenceCheckerOrSetterMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDefaultMethod(ExecutableElement method) {
|
public static boolean isDefaultMethod(ExecutableElement method) {
|
||||||
|
@ -32,7 +32,7 @@ import org.mapstruct.ap.internal.prism.MapperConfigPrism;
|
|||||||
import org.mapstruct.ap.internal.prism.MapperPrism;
|
import org.mapstruct.ap.internal.prism.MapperPrism;
|
||||||
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
|
import org.mapstruct.ap.internal.prism.MappingInheritanceStrategyPrism;
|
||||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||||
import org.mapstruct.ap.internal.prism.SourceValuePresenceCheckStrategy;
|
import org.mapstruct.ap.internal.prism.NullValueCheckStrategy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and
|
* Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and
|
||||||
@ -136,6 +136,15 @@ public class MapperConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NullValueCheckStrategy getNullValueCheckStrategy() {
|
||||||
|
if ( mapperConfigPrism != null && mapperPrism.values.nullValueCheckStrategy() == null ) {
|
||||||
|
return NullValueCheckStrategy.valueOf( mapperConfigPrism.nullValueCheckStrategy() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return NullValueCheckStrategy.valueOf( mapperPrism.nullValueCheckStrategy() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMapToDefault(NullValueMappingStrategyPrism mapNullToDefault) {
|
public boolean isMapToDefault(NullValueMappingStrategyPrism mapNullToDefault) {
|
||||||
|
|
||||||
// check on method level
|
// check on method level
|
||||||
@ -185,21 +194,4 @@ public class MapperConfiguration {
|
|||||||
return mapperPrism.mirror;
|
return mapperPrism.mirror;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() {
|
|
||||||
if ( mapperConfigPrism != null && mapperPrism.values.sourceValuePresenceCheckStrategy() == null ) {
|
|
||||||
return SourceValuePresenceCheckStrategy.valueOf( mapperConfigPrism.sourceValuePresenceCheckStrategy() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return SourceValuePresenceCheckStrategy.valueOf( mapperPrism.sourceValuePresenceCheckStrategy() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSetSourceValuePresenceCheckStrategy() {
|
|
||||||
if ( mapperConfigPrism != null && mapperPrism.values.sourceValuePresenceCheckStrategy() == null ) {
|
|
||||||
return mapperConfigPrism.values.sourceValuePresenceCheckStrategy() != null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return mapperPrism.values.sourceValuePresenceCheckStrategy() != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.internal.util;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple locator for SPI implementations.
|
||||||
|
*
|
||||||
|
* @author Christian Schuster
|
||||||
|
*/
|
||||||
|
public class Services {
|
||||||
|
|
||||||
|
private Services() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(Class<T> serviceType, T defaultValue) {
|
||||||
|
|
||||||
|
Iterator<T> services = ServiceLoader.load( serviceType, Services.class.getClassLoader() ).iterator();
|
||||||
|
|
||||||
|
T result;
|
||||||
|
if ( services.hasNext() ) {
|
||||||
|
result = services.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = defaultValue;
|
||||||
|
}
|
||||||
|
if ( services.hasNext() ) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Multiple implementations have been found for the service provider interface" );
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.naming;
|
package org.mapstruct.ap.spi;
|
||||||
|
|
||||||
import java.beans.Introspector;
|
import java.beans.Introspector;
|
||||||
|
|
||||||
@ -28,8 +28,6 @@ import javax.lang.model.type.TypeMirror;
|
|||||||
import javax.lang.model.util.SimpleElementVisitor6;
|
import javax.lang.model.util.SimpleElementVisitor6;
|
||||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||||
|
|
||||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
|
||||||
import org.mapstruct.ap.spi.MethodType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default JavaBeans-compliant implementation of the {@link AccessorNamingStrategy} service provider interface.
|
* The default JavaBeans-compliant implementation of the {@link AccessorNamingStrategy} service provider interface.
|
||||||
@ -43,9 +41,6 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
|||||||
if ( isGetterMethod( method ) ) {
|
if ( isGetterMethod( method ) ) {
|
||||||
return MethodType.GETTER;
|
return MethodType.GETTER;
|
||||||
}
|
}
|
||||||
else if ( isPresenceCheckMethod( method ) ) {
|
|
||||||
return MethodType.PRESENCE_CHECKER;
|
|
||||||
}
|
|
||||||
else if ( isSetterMethod( method ) ) {
|
else if ( isSetterMethod( method ) ) {
|
||||||
return MethodType.SETTER;
|
return MethodType.SETTER;
|
||||||
}
|
}
|
||||||
@ -70,14 +65,6 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
|||||||
return isNonBooleanGetterName || ( isBooleanGetterName && returnTypeIsBoolean );
|
return isNonBooleanGetterName || ( isBooleanGetterName && returnTypeIsBoolean );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPresenceCheckMethod(ExecutableElement method) {
|
|
||||||
String methodName = method.getSimpleName().toString();
|
|
||||||
|
|
||||||
return methodName.startsWith( "has" ) && methodName.length() > 3 &&
|
|
||||||
( method.getReturnType().getKind() == TypeKind.BOOLEAN ||
|
|
||||||
"java.lang.Boolean".equals( getQualifiedName( method.getReturnType() ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSetterMethod(ExecutableElement method) {
|
public boolean isSetterMethod(ExecutableElement method) {
|
||||||
String methodName = method.getSimpleName().toString();
|
String methodName = method.getSimpleName().toString();
|
||||||
|
|
||||||
@ -92,8 +79,8 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) {
|
public String getPropertyName(ExecutableElement getterOrSetterMethod) {
|
||||||
String methodName = getterOrHasserOrSetterMethod.getSimpleName().toString();
|
String methodName = getterOrSetterMethod.getSimpleName().toString();
|
||||||
return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
|
return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +95,7 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
|||||||
return "get" + property.substring( 0, 1 ).toUpperCase() + property.substring( 1 );
|
return "get" + property.substring( 0, 1 ).toUpperCase() + property.substring( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getQualifiedName(TypeMirror type) {
|
protected static String getQualifiedName(TypeMirror type) {
|
||||||
DeclaredType declaredType = type.accept(
|
DeclaredType declaredType = type.accept(
|
||||||
new SimpleTypeVisitor6<DeclaredType, Void>() {
|
new SimpleTypeVisitor6<DeclaredType, Void>() {
|
||||||
@Override
|
@Override
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 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.spi;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.lang.model.element.ExecutableElement;
|
||||||
|
import javax.lang.model.type.TypeKind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default JavaBeans-compliant implementation of the {@link AccessorNamingStrategy} service provider interface.
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class PresenceCheckAccessorNamingStrategy
|
||||||
|
extends DefaultAccessorNamingStrategy
|
||||||
|
implements AccessorNamingStrategy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodType getMethodType(ExecutableElement method) {
|
||||||
|
if ( isPresenceCheckMethod( method ) ) {
|
||||||
|
return MethodType.PRESENCE_CHECKER;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return super.getMethodType( method );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isPresenceCheckMethod(ExecutableElement method) {
|
||||||
|
String methodName = method.getSimpleName().toString();
|
||||||
|
|
||||||
|
return methodName.startsWith( "has" ) && methodName.length() > 3 &&
|
||||||
|
( method.getReturnType().getKind() == TypeKind.BOOLEAN ||
|
||||||
|
"java.lang.Boolean".equals( getQualifiedName( method.getReturnType() ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,15 +23,23 @@
|
|||||||
if ( ${sourceParameter.name} == null ) {
|
if ( ${sourceParameter.name} == null ) {
|
||||||
return ${returnType.null};
|
return ${returnType.null};
|
||||||
}
|
}
|
||||||
<#list propertyEntries as entry>
|
<#list propertyEntries as entry>
|
||||||
<@includeModel object=entry.type/> ${entry.name} = <#if entry_index == 0>${sourceParameter.name}.${entry.accessorName}()<#else>${propertyEntries[entry_index-1].name}.${entry.accessorName}()</#if>;
|
<#if entry.presenceChecker?? >
|
||||||
|
if ( !<@localVarName index=entry_index/>.${entry.presenceChecker.simpleName}() ) {
|
||||||
|
return ${returnType.null};
|
||||||
|
}
|
||||||
|
</#if>
|
||||||
|
<@includeModel object=entry.type/> ${entry.name} = <@localVarName index=entry_index/>.${entry.accessorName}();
|
||||||
|
<#if !entry.presenceChecker?? >
|
||||||
<#if !entry.type.primitive>
|
<#if !entry.type.primitive>
|
||||||
if ( ${entry.name} == null ) {
|
if ( ${entry.name} == null ) {
|
||||||
return ${returnType.null};
|
return ${returnType.null};
|
||||||
}
|
}
|
||||||
</#if>
|
</#if>
|
||||||
|
</#if>
|
||||||
<#if !entry_has_next>
|
<#if !entry_has_next>
|
||||||
return ${entry.name};
|
return ${entry.name};
|
||||||
</#if>
|
</#if>
|
||||||
</#list>
|
</#list>
|
||||||
}
|
}
|
||||||
|
<#macro localVarName index><#if index == 0>${sourceParameter.name}<#else>${propertyEntries[index-1].name}</#if></#macro>
|
@ -18,7 +18,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
if ( ${sourceReference} != null ) {
|
if ( <#if sourcePresenceChecker?? >${sourcePresenceChecker}<#else>${sourceReference} != null</#if> ) {
|
||||||
<@includeModel object=assignment
|
<@includeModel object=assignment
|
||||||
targetBeanName=ext.targetBeanName
|
targetBeanName=ext.targetBeanName
|
||||||
existingInstanceMapping=ext.existingInstanceMapping
|
existingInstanceMapping=ext.existingInstanceMapping
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
if ( ${sourceReference} != null ) {
|
if ( <#if sourcePresenceChecker?? >${sourcePresenceChecker}<#else>${sourceReference} != null</#if> ) {
|
||||||
<@includeModel object=assignment
|
<@includeModel object=assignment
|
||||||
targetBeanName=ext.targetBeanName
|
targetBeanName=ext.targetBeanName
|
||||||
existingInstanceMapping=ext.existingInstanceMapping
|
existingInstanceMapping=ext.existingInstanceMapping
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2016 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.presencecheck;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.fest.assertions.Assertions;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mapstruct.ap.testutil.WithClasses;
|
|
||||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test for correct handling of source presence checks.
|
|
||||||
*
|
|
||||||
* @author Sean Huang
|
|
||||||
*/
|
|
||||||
@WithClasses({
|
|
||||||
SourceTargetMapper.class,
|
|
||||||
MyObject.class,
|
|
||||||
CustomMapper.class,
|
|
||||||
MyLongWrapper.class,
|
|
||||||
Source.class,
|
|
||||||
Target.class,
|
|
||||||
SourceWtCheck.class,
|
|
||||||
TargetWtCheck.class
|
|
||||||
})
|
|
||||||
@RunWith(AnnotationProcessorTestRunner.class)
|
|
||||||
public class PresenceCheckTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSourceNoPresenceCheckWithIsNullheck() {
|
|
||||||
SourceWtCheck source = new SourceWtCheck();
|
|
||||||
source.setHasSomeList( false );
|
|
||||||
source.setHasSomeLong2( false );
|
|
||||||
|
|
||||||
TargetWtCheck target = SourceTargetMapper.INSTANCE.sourceToTargetWithIsNullCheck( source );
|
|
||||||
|
|
||||||
//No null check for primitive type
|
|
||||||
Assert.assertEquals( 0, target.getSomePrimitiveDouble(), 0.01 );
|
|
||||||
Assert.assertEquals( null, target.getSomeInteger() );
|
|
||||||
Assert.assertEquals( null, target.getNoCheckObject() );
|
|
||||||
Assert.assertEquals( 0, target.getNoCheckPrimitive() );
|
|
||||||
Assert.assertEquals( null, target.getSomeLong1() );
|
|
||||||
Assert.assertEquals( null, target.getSomeLong2() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test( expected = NullPointerException.class )
|
|
||||||
public void testSourceNoPresenceCheckWithIsNullInlineCheck() {
|
|
||||||
SourceWtCheck source = new SourceWtCheck();
|
|
||||||
source.setHasSomeList( false );
|
|
||||||
|
|
||||||
//No null check for Mapper, if sourceValuePresenceCheckStrategy = IS_NULL_INLINE
|
|
||||||
TargetWtCheck target = SourceTargetMapper.INSTANCE.sourceToTargetWithIsNullInlineCheck( source );
|
|
||||||
|
|
||||||
Assert.assertEquals( null, target.getSomeLong2() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSourcePresenceCheckWithCustom() {
|
|
||||||
MyObject object = new MyObject();
|
|
||||||
MyLongWrapper longWrapper = new MyLongWrapper();
|
|
||||||
longWrapper.setMyLong( 2L );
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
list.add( "first" );
|
|
||||||
list.add( "second" );
|
|
||||||
|
|
||||||
Source source = new Source();
|
|
||||||
|
|
||||||
source.setSomeObject( object );
|
|
||||||
source.setSomePrimitiveDouble( 5.0 );
|
|
||||||
source.setSomeInteger( 7 );
|
|
||||||
source.setSomeLong1( 2L );
|
|
||||||
source.setHasSomeLong2( false );
|
|
||||||
source.setSomeList( list );
|
|
||||||
|
|
||||||
Target target = SourceTargetMapper.INSTANCE.sourceToTargetWithCustom( source );
|
|
||||||
|
|
||||||
Assert.assertEquals( object, target.getSomeObject() );
|
|
||||||
Assert.assertEquals( 5.0, target.getSomePrimitiveDouble(), 0.01 );
|
|
||||||
Assert.assertEquals( (Integer) 7, target.getSomeInteger() );
|
|
||||||
Assert.assertEquals( longWrapper.getMyLong(), target.getSomeLong1().getMyLong() );
|
|
||||||
Assert.assertEquals( null, target.getSomeLong2() );
|
|
||||||
|
|
||||||
Assertions.assertThat( target.getSomeList() ).containsExactly( "first", "second" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateWithCustom() {
|
|
||||||
MyObject object = new MyObject();
|
|
||||||
MyLongWrapper longWrapper = new MyLongWrapper();
|
|
||||||
longWrapper.setMyLong( 2L );
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
list.add( "first" );
|
|
||||||
list.add( "second" );
|
|
||||||
|
|
||||||
Source source = new Source();
|
|
||||||
|
|
||||||
source.setSomeObject( object );
|
|
||||||
|
|
||||||
source.setSomePrimitiveDouble( 5.0 );
|
|
||||||
source.setHasSomePrimitiveDouble( false );
|
|
||||||
|
|
||||||
source.setSomeInteger( 7 );
|
|
||||||
source.setSomeLong1( 2L );
|
|
||||||
|
|
||||||
source.setSomeLong2( 4L );
|
|
||||||
source.setHasSomeLong2( false );
|
|
||||||
|
|
||||||
source.setSomeList( list );
|
|
||||||
|
|
||||||
Target target = new Target();
|
|
||||||
|
|
||||||
SourceTargetMapper.INSTANCE.sourceToTargetWithCustom( source, target );
|
|
||||||
|
|
||||||
Assert.assertEquals( object, target.getSomeObject() );
|
|
||||||
Assert.assertEquals( 0, target.getSomePrimitiveDouble(), 0.01 );
|
|
||||||
Assert.assertEquals( (Integer) 7, target.getSomeInteger() );
|
|
||||||
Assert.assertEquals( longWrapper.getMyLong(), target.getSomeLong1().getMyLong() );
|
|
||||||
Assert.assertEquals( null, target.getSomeLong2() );
|
|
||||||
|
|
||||||
Assertions.assertThat( target.getSomeList() ).containsExactly( "first", "second" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSourcePresenceCheckWithCustomAndDefaultValue() {
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
list.add( "first" );
|
|
||||||
list.add( "second" );
|
|
||||||
|
|
||||||
Source source = new Source();
|
|
||||||
source.setSomeList( list );
|
|
||||||
|
|
||||||
source.setHasSomePrimitiveDouble( false );
|
|
||||||
source.setHasSomeInteger( false );
|
|
||||||
source.setHasSomeLong1( false );
|
|
||||||
source.setHasSomeLong2( false );
|
|
||||||
|
|
||||||
Target target = SourceTargetMapper.INSTANCE.sourceToTargetWithCustomAndDefault( source );
|
|
||||||
|
|
||||||
Assert.assertEquals( null, target.getSomeObject() );
|
|
||||||
|
|
||||||
//Support default value for primitive type if there is hasX method and config is on
|
|
||||||
Assert.assertEquals( 111.1, target.getSomePrimitiveDouble(), 0.01 );
|
|
||||||
Assert.assertEquals( (Integer) 222, target.getSomeInteger() );
|
|
||||||
Assert.assertEquals( (Long) 333L, target.getSomeLong1().getMyLong() );
|
|
||||||
Assert.assertEquals( (Long) 444L, target.getSomeLong2().getMyLong() );
|
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
|
||||||
Assert.assertEquals( list.get( i ), target.getSomeList().get( i ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2012-2016 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.presencecheck;
|
|
||||||
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.CUSTOM;
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL;
|
|
||||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
|
||||||
|
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.Mapping;
|
|
||||||
import org.mapstruct.MappingTarget;
|
|
||||||
import org.mapstruct.Mappings;
|
|
||||||
import org.mapstruct.factory.Mappers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Sean Huang
|
|
||||||
*/
|
|
||||||
@Mapper(uses = { CustomMapper.class }, sourceValuePresenceCheckStrategy = CUSTOM)
|
|
||||||
public interface SourceTargetMapper {
|
|
||||||
|
|
||||||
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
|
||||||
|
|
||||||
Target sourceToTargetWithCustom(Source source);
|
|
||||||
|
|
||||||
void sourceToTargetWithCustom(Source source, @MappingTarget Target target);
|
|
||||||
|
|
||||||
@Mappings( {
|
|
||||||
@Mapping(target = "somePrimitiveDouble", defaultValue = "111.1"),
|
|
||||||
@Mapping(target = "someInteger", defaultValue = "222"),
|
|
||||||
@Mapping(target = "someLong1", defaultValue = "333"),
|
|
||||||
@Mapping(target = "someLong2", defaultValue = "444"),
|
|
||||||
} )
|
|
||||||
Target sourceToTargetWithCustomAndDefault(Source source);
|
|
||||||
|
|
||||||
@Mappings( {
|
|
||||||
@Mapping(target = "somePrimitiveDouble", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "someInteger", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "noCheckObject", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "noCheckPrimitive", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "someLong1", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
} )
|
|
||||||
TargetWtCheck sourceToTargetWithIsNullCheck(SourceWtCheck source);
|
|
||||||
|
|
||||||
@Mappings( {
|
|
||||||
@Mapping(target = "noCheckObject", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "noCheckPrimitive", sourceValuePresenceCheckStrategy = IS_NULL),
|
|
||||||
@Mapping(target = "someLong2", sourceValuePresenceCheckStrategy = IS_NULL_INLINE),
|
|
||||||
} )
|
|
||||||
TargetWtCheck sourceToTargetWithIsNullInlineCheck(SourceWtCheck source);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Seeing exception below since there is no presence check method on source.
|
|
||||||
*
|
|
||||||
* org.junit.ComparisonFailure: [Compilation failed. Diagnostics: [DiagnosticDescriptor:
|
|
||||||
* ERROR SourceTargetPresenceCheckMapper.java:53 Using custom source value presence checking strategy,
|
|
||||||
* but no presence checker found for property "int noCheckPrimitive" in source type.]]
|
|
||||||
* expected:<[SUCCEED]ED> but was:<[FAIL]ED>
|
|
||||||
*
|
|
||||||
@Mappings( {
|
|
||||||
@Mapping(target = "someDouble", defaultValue = "111.1"),
|
|
||||||
@Mapping(target = "someInteger", defaultValue = "222"),
|
|
||||||
@Mapping(target = "someLong", defaultValue = "333"),
|
|
||||||
} )
|
|
||||||
TargetWtCheck sourceToTargetWithConfigOn(SourceWtCheck source);
|
|
||||||
*/
|
|
||||||
}
|
|
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
RockFestivalMapper.class,
|
||||||
|
RockFestivalSource.class,
|
||||||
|
RockFestivalTarget.class,
|
||||||
|
RockFestivalMapperConfig.class,
|
||||||
|
RockFestivalMapperWithConfig.class,
|
||||||
|
RockFestivalMapperOveridingConfig.class,
|
||||||
|
Stage.class
|
||||||
|
})
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
public class PresenceCheckTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCallingMappingMethodWithNullSource() {
|
||||||
|
|
||||||
|
RockFestivalSource source = new RockFestivalSource();
|
||||||
|
RockFestivalTarget target = RockFestivalMapper.INSTANCE.map( source );
|
||||||
|
assertThat( target.getStage() ).isNull();
|
||||||
|
|
||||||
|
source.setArtistName( "New Order" );
|
||||||
|
target = RockFestivalMapper.INSTANCE.map( source );
|
||||||
|
assertThat( target.getStage() ).isEqualTo( Stage.THE_BARN );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCallingMappingMethodWithNullSourceWithConfig() {
|
||||||
|
|
||||||
|
RockFestivalSource source = new RockFestivalSource();
|
||||||
|
RockFestivalTarget target = RockFestivalMapperWithConfig.INSTANCE.map( source );
|
||||||
|
assertThat( target.getStage() ).isNull();
|
||||||
|
|
||||||
|
source.setArtistName( "New Order" );
|
||||||
|
target = RockFestivalMapperWithConfig.INSTANCE.map( source );
|
||||||
|
assertThat( target.getStage() ).isEqualTo( Stage.THE_BARN );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test( expected = IllegalArgumentException.class )
|
||||||
|
public void testCallingMappingMethodWithNullSourceOveridingConfig() {
|
||||||
|
|
||||||
|
RockFestivalSource source = new RockFestivalSource();
|
||||||
|
RockFestivalMapperOveridingConfig.INSTANCE.map( source );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.NullValueCheckStrategy;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
@Mapper( nullValueCheckStrategy = NullValueCheckStrategy.ALLWAYS )
|
||||||
|
public abstract class RockFestivalMapper {
|
||||||
|
|
||||||
|
public static final RockFestivalMapper INSTANCE = Mappers.getMapper( RockFestivalMapper.class );
|
||||||
|
|
||||||
|
@Mapping( target = "stage", source = "artistName" )
|
||||||
|
public abstract RockFestivalTarget map( RockFestivalSource in );
|
||||||
|
|
||||||
|
public Stage artistToStage( String name ) {
|
||||||
|
return Stage.forArtist( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -16,30 +16,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct;
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
import org.mapstruct.MapperConfig;
|
||||||
|
import org.mapstruct.NullValueCheckStrategy;
|
||||||
/**
|
/**
|
||||||
* Strategy to decide how to check null or hasX method before mapping
|
|
||||||
*
|
*
|
||||||
* @author Sean Huang
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public enum SourceValuePresenceCheckStrategy {
|
@MapperConfig( nullValueCheckStrategy = NullValueCheckStrategy.ALLWAYS )
|
||||||
|
public interface RockFestivalMapperConfig {
|
||||||
|
|
||||||
/**
|
|
||||||
* Only check != null for inline conversions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
IS_NULL_INLINE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Always check != null, no matter whether it's an inline or method conversion
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
IS_NULL,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Will invoke custom hasX() method, before mapping,
|
|
||||||
* name to be given through the accessor naming strategy
|
|
||||||
*/
|
|
||||||
CUSTOM;
|
|
||||||
}
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
import static org.mapstruct.NullValueCheckStrategy.ON_IMPLICIT_CONVERSION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
@Mapper( config = RockFestivalMapperConfig.class, nullValueCheckStrategy = ON_IMPLICIT_CONVERSION )
|
||||||
|
public abstract class RockFestivalMapperOveridingConfig {
|
||||||
|
|
||||||
|
public static final RockFestivalMapperOveridingConfig INSTANCE =
|
||||||
|
Mappers.getMapper( RockFestivalMapperOveridingConfig.class );
|
||||||
|
|
||||||
|
@Mapping( target = "stage", source = "artistName" )
|
||||||
|
public abstract RockFestivalTarget map( RockFestivalSource in );
|
||||||
|
|
||||||
|
public Stage artistToStage( String name ) {
|
||||||
|
return Stage.forArtist( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -16,30 +16,28 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Huang
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class TargetWtCheck extends Target {
|
@Mapper( config = RockFestivalMapperConfig.class )
|
||||||
|
public abstract class RockFestivalMapperWithConfig {
|
||||||
|
|
||||||
private int noCheckPrimitive;
|
public static final RockFestivalMapperWithConfig INSTANCE =
|
||||||
private String noCheckObject;
|
Mappers.getMapper( RockFestivalMapperWithConfig.class );
|
||||||
|
|
||||||
public int getNoCheckPrimitive() {
|
@Mapping( target = "stage", source = "artistName" )
|
||||||
return noCheckPrimitive;
|
public abstract RockFestivalTarget map( RockFestivalSource in );
|
||||||
|
|
||||||
|
public Stage artistToStage( String name ) {
|
||||||
|
return Stage.forArtist( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNoCheckPrimitive(int noCheckPrimitive) {
|
|
||||||
this.noCheckPrimitive = noCheckPrimitive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNoCheckObject() {
|
|
||||||
return noCheckObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNoCheckObject(String noCheckObject) {
|
|
||||||
this.noCheckObject = noCheckObject;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -16,20 +16,22 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
import org.mapstruct.Mapper;
|
|
||||||
import org.mapstruct.SourceValuePresenceCheckStrategy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Huang
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
@Mapper( sourceValuePresenceCheckStrategy = SourceValuePresenceCheckStrategy.IS_NULL_INLINE )
|
public class RockFestivalSource {
|
||||||
public class CustomMapper {
|
|
||||||
|
|
||||||
public MyLongWrapper toMyLongWrapperViaPrimitive(Long primitive) {
|
private String artistName;
|
||||||
MyLongWrapper wrapper = new MyLongWrapper();
|
|
||||||
wrapper.setMyLong( primitive );
|
public String getArtistName() {
|
||||||
return wrapper;
|
return artistName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setArtistName(String artistName) {
|
||||||
|
this.artistName = artistName;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -16,23 +16,22 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class MyLongWrapper {
|
public class RockFestivalTarget {
|
||||||
|
|
||||||
private Long myLong;
|
private Stage stage;
|
||||||
|
|
||||||
public Long getMyLong() {
|
public Stage getStage() {
|
||||||
return myLong;
|
return stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMyLong(Long myLong) {
|
public void setStage(Stage stage) {
|
||||||
myLong.longValue();
|
this.stage = stage;
|
||||||
this.myLong = myLong;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public enum Stage {
|
||||||
|
|
||||||
|
MAIN("Paul McCartney", "Ellie Goulding", "Disclosure", "Kaiser Chiefs", "Rammstein"),
|
||||||
|
KLUB_C("James Blake", "Lost Frequencies"),
|
||||||
|
THE_BARN("New Order", "Year and Years");
|
||||||
|
|
||||||
|
private final List<String> artists;
|
||||||
|
|
||||||
|
Stage(String... artist) {
|
||||||
|
this.artists = Arrays.asList( artist );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stage forArtist( String name ) {
|
||||||
|
|
||||||
|
if ( name == null ) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Stage value : Stage.values() ) {
|
||||||
|
if ( value.artists.contains( name ) ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -16,30 +16,31 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Sean Huang
|
*
|
||||||
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class SourceWtCheck extends Source {
|
public class GoalKeeper {
|
||||||
|
|
||||||
private int noCheckPrimitive;
|
private String name;
|
||||||
private String noCheckObject;
|
private boolean hasName = true;
|
||||||
|
|
||||||
public int getNoCheckPrimitive() {
|
public String getName() {
|
||||||
return noCheckPrimitive;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNoCheckPrimitive(int noCheckPrimitive) {
|
public void setName(String name) {
|
||||||
this.noCheckPrimitive = noCheckPrimitive;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNoCheckObject() {
|
public boolean hasName() {
|
||||||
return noCheckObject;
|
return hasName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNoCheckObject(String noCheckObject) {
|
public void setHasName(boolean hasName) {
|
||||||
this.noCheckObject = noCheckObject;
|
this.hasName = hasName;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,217 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.spi.PresenceCheckAccessorNamingStrategy;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
import org.mapstruct.ap.testutil.WithServiceImplementation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for correct handling of source presence checks.
|
||||||
|
*
|
||||||
|
* @author Sean Huang
|
||||||
|
*/
|
||||||
|
@WithClasses({
|
||||||
|
SourceTargetMapper.class,
|
||||||
|
Source.class,
|
||||||
|
Target.class,
|
||||||
|
SoccerTeamMapper.class,
|
||||||
|
SoccerTeamSource.class,
|
||||||
|
GoalKeeper.class,
|
||||||
|
SoccerTeamTarget.class
|
||||||
|
})
|
||||||
|
@WithServiceImplementation( PresenceCheckAccessorNamingStrategy.class )
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
public class PresenceCheckTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSourcesPresent() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setSomePrimitiveDouble( 5.0 );
|
||||||
|
source.setSomeInteger( 7 );
|
||||||
|
source.setSomeList( Arrays.asList( "first", "second" ) );
|
||||||
|
source.setSomeArray( new String[]{ "x", "y" } );
|
||||||
|
|
||||||
|
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 5.0 );
|
||||||
|
assertThat( target.getSomeInteger() ).isEqualTo( 7 );
|
||||||
|
assertThat( target.getSomeList() ).containsExactly( "first", "second" );
|
||||||
|
assertThat( target.getSomeArray() ).isEqualTo( new String[]{ "x", "y"} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSourcesAbsent() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setHasSomePrimitiveDouble( false );
|
||||||
|
source.setHasSomeInteger( false );
|
||||||
|
source.setHasSomeList( false );
|
||||||
|
source.setHasSomeArray( false );
|
||||||
|
|
||||||
|
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 0d );
|
||||||
|
assertThat( target.getSomeInteger() ).isNull();
|
||||||
|
assertThat( target.getSomeList() ).isNull();
|
||||||
|
assertThat( target.getSomeArray() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateMethodWithSourcesPresent() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setSomePrimitiveDouble( 5.0 );
|
||||||
|
source.setSomeInteger( 7 );
|
||||||
|
source.setSomeList( Arrays.asList( "first", "second" ) );
|
||||||
|
source.setSomeArray( new String[]{ "x", "y" } );
|
||||||
|
|
||||||
|
Target target = new Target();
|
||||||
|
SourceTargetMapper.INSTANCE.sourceToTarget( source, target );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 5.0 );
|
||||||
|
assertThat( target.getSomeInteger() ).isEqualTo( 7 );
|
||||||
|
assertThat( target.getSomeList() ).containsExactly( "first", "second" );
|
||||||
|
assertThat( target.getSomeArray() ).isEqualTo( new String[]{ "x", "y"} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateMethodWithSourcesAbsent() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setHasSomePrimitiveDouble( false );
|
||||||
|
source.setHasSomeInteger( false );
|
||||||
|
source.setHasSomeList( false );
|
||||||
|
source.setHasSomeArray( false );
|
||||||
|
|
||||||
|
Target target = new Target();
|
||||||
|
SourceTargetMapper.INSTANCE.sourceToTarget( source, target );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 0d );
|
||||||
|
assertThat( target.getSomeInteger() ).isNull();
|
||||||
|
assertThat( target.getSomeList() ).isNull();
|
||||||
|
assertThat( target.getSomeArray() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSourcesPresentAndDefault() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setSomePrimitiveDouble( 5.0 );
|
||||||
|
source.setSomeInteger( 7 );
|
||||||
|
source.setSomeList( Arrays.asList( "first", "second" ) );
|
||||||
|
source.setSomeArray( new String[]{ "x", "y" } );
|
||||||
|
|
||||||
|
Target target = SourceTargetMapper.INSTANCE.sourceToTargetWitDefaults( source );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 5.0 );
|
||||||
|
assertThat( target.getSomeInteger() ).isEqualTo( 7 );
|
||||||
|
assertThat( target.getSomeList() ).containsExactly( "first", "second" );
|
||||||
|
assertThat( target.getSomeArray() ).isEqualTo( new String[]{ "x", "y"} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWithSourcesAbsentAndDefault() {
|
||||||
|
|
||||||
|
Source source = new Source();
|
||||||
|
|
||||||
|
source.setHasSomePrimitiveDouble( false );
|
||||||
|
source.setHasSomeInteger( false );
|
||||||
|
source.setHasSomeList( false );
|
||||||
|
source.setHasSomeArray( false );
|
||||||
|
|
||||||
|
Target target = SourceTargetMapper.INSTANCE.sourceToTargetWitDefaults( source );
|
||||||
|
|
||||||
|
assertThat( target.getSomePrimitiveDouble() ).isEqualTo( 111.1d );
|
||||||
|
assertThat( target.getSomeInteger() ).isEqualTo( 222 );
|
||||||
|
assertThat( target.getSomeList() ).containsExactly( "a", "b" );
|
||||||
|
assertThat( target.getSomeArray() ).isEqualTo( new String[]{ "u", "v"} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdderWithSourcesPresent() {
|
||||||
|
|
||||||
|
SoccerTeamSource soccerTeamSource = new SoccerTeamSource();
|
||||||
|
soccerTeamSource.setPlayers( Arrays.asList( "pele", "cruyf" ) );
|
||||||
|
|
||||||
|
SoccerTeamTarget target = SoccerTeamMapper.INSTANCE.mapAdder( soccerTeamSource );
|
||||||
|
|
||||||
|
assertThat( target.getPlayers() ).containsExactly( "pele", "cruyf" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdderWithSourcesAbsent() {
|
||||||
|
|
||||||
|
SoccerTeamSource soccerTeamSource = new SoccerTeamSource();
|
||||||
|
soccerTeamSource.setHasPlayers( false );
|
||||||
|
|
||||||
|
SoccerTeamTarget target = SoccerTeamMapper.INSTANCE.mapAdder( soccerTeamSource );
|
||||||
|
|
||||||
|
assertThat( target.getPlayers() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNestedWithSourcesPresent() {
|
||||||
|
|
||||||
|
SoccerTeamSource soccerTeamSource = new SoccerTeamSource();
|
||||||
|
GoalKeeper goalKeeper = new GoalKeeper();
|
||||||
|
goalKeeper.setName( "Buffon" );
|
||||||
|
soccerTeamSource.setGoalKeeper( goalKeeper );
|
||||||
|
|
||||||
|
SoccerTeamTarget target = SoccerTeamMapper.INSTANCE.mapNested( soccerTeamSource );
|
||||||
|
|
||||||
|
assertThat( target.getGoalKeeperName() ).isEqualTo( "Buffon" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNestedWithSourcesAbsentOnRootLevel() {
|
||||||
|
|
||||||
|
SoccerTeamSource soccerTeamSource = new SoccerTeamSource();
|
||||||
|
soccerTeamSource.setHasGoalKeeper( false );
|
||||||
|
|
||||||
|
SoccerTeamTarget target = SoccerTeamMapper.INSTANCE.mapNested( soccerTeamSource );
|
||||||
|
|
||||||
|
assertThat( target.getGoalKeeperName() ).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNestedWithSourcesAbsentOnNestingLevel() {
|
||||||
|
|
||||||
|
SoccerTeamSource soccerTeamSource = new SoccerTeamSource();
|
||||||
|
GoalKeeper goalKeeper = new GoalKeeper();
|
||||||
|
goalKeeper.setHasName( false );
|
||||||
|
soccerTeamSource.setGoalKeeper( goalKeeper );
|
||||||
|
|
||||||
|
SoccerTeamTarget target = SoccerTeamMapper.INSTANCE.mapNested( soccerTeamSource );
|
||||||
|
|
||||||
|
assertThat( target.getGoalKeeperName() ).isNull();
|
||||||
|
}
|
||||||
|
}
|
@ -16,30 +16,31 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.internal.prism;
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
import org.mapstruct.CollectionMappingStrategy;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prism for the enum {@link org.mapstruct.SourceValuePresenceCheckStrategy}
|
|
||||||
*
|
*
|
||||||
* @author Sean Huang
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public enum SourceValuePresenceCheckStrategy {
|
@Mapper( collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED )
|
||||||
/**
|
public interface SoccerTeamMapper {
|
||||||
* Only check != null for inline conversions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
IS_NULL_INLINE,
|
|
||||||
|
|
||||||
/**
|
SoccerTeamMapper INSTANCE = Mappers.getMapper( SoccerTeamMapper.class );
|
||||||
* Always check != null, no matter whether it's an inline or method conversion
|
|
||||||
*
|
@Mapping( target = "goalKeeperName", ignore = true )
|
||||||
*/
|
SoccerTeamTarget mapAdder( SoccerTeamSource in );
|
||||||
IS_NULL,
|
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(target = "players", ignore = true),
|
||||||
|
@Mapping(target = "goalKeeperName", source = "goalKeeper.name")
|
||||||
|
})
|
||||||
|
SoccerTeamTarget mapNested( SoccerTeamSource in );
|
||||||
|
|
||||||
/**
|
|
||||||
* Will invoke custom hasX() method, before mapping,
|
|
||||||
* name to be given through the accessor naming strategy
|
|
||||||
*/
|
|
||||||
CUSTOM;
|
|
||||||
}
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class SoccerTeamSource {
|
||||||
|
|
||||||
|
private List<String> players;
|
||||||
|
private boolean hasPlayers = true;
|
||||||
|
|
||||||
|
private GoalKeeper goalKeeper;
|
||||||
|
private boolean hasGoalKeeper = true;
|
||||||
|
|
||||||
|
public boolean hasPlayers() {
|
||||||
|
return hasPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasPlayers(boolean has) {
|
||||||
|
this.hasPlayers = has;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPlayers() {
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayers(List<String> players) {
|
||||||
|
this.players = players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GoalKeeper getGoalKeeper() {
|
||||||
|
return goalKeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoalKeeper(GoalKeeper goalKeeper) {
|
||||||
|
this.goalKeeper = goalKeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasGoalKeeper() {
|
||||||
|
return hasGoalKeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasGoalKeeper(boolean hasGoalKeeper) {
|
||||||
|
this.hasGoalKeeper = hasGoalKeeper;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sjaak Derksen
|
||||||
|
*/
|
||||||
|
public class SoccerTeamTarget {
|
||||||
|
|
||||||
|
private List<String> players;
|
||||||
|
private String goalKeeperName;
|
||||||
|
|
||||||
|
|
||||||
|
public List<String> getPlayers() {
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(String player) {
|
||||||
|
if ( this.players == null ) {
|
||||||
|
this.players = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
this.players.add( player );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoalKeeperName() {
|
||||||
|
return goalKeeperName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoalKeeperName(String goalKeeperName) {
|
||||||
|
this.goalKeeperName = goalKeeperName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -25,39 +25,17 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Source {
|
public class Source {
|
||||||
|
|
||||||
private MyObject someObject;
|
|
||||||
private boolean hasSomeObject = true;
|
|
||||||
|
|
||||||
private double somePrimitiveDouble;
|
private double somePrimitiveDouble;
|
||||||
private boolean hasPrimitiveSomeDouble = true;
|
private boolean hasPrimitiveSomeDouble = true;
|
||||||
|
|
||||||
private Integer someInteger;
|
private Integer someInteger;
|
||||||
private boolean hasSomeInteger = true;
|
private boolean hasSomeInteger = true;
|
||||||
|
|
||||||
private Long someLong1;
|
|
||||||
private boolean hasSomeLong1 = true;
|
|
||||||
|
|
||||||
private Long someLong2;
|
|
||||||
private boolean hasSomeLong2 = true;
|
|
||||||
|
|
||||||
private List<String> someList;
|
private List<String> someList;
|
||||||
private boolean hasSomeList = true;
|
private boolean hasSomeList = true;
|
||||||
|
|
||||||
public boolean hasSomeObject() {
|
private String[] someArray;
|
||||||
return hasSomeObject;
|
private boolean hasSomeArray = true;
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasSomeObject(boolean has) {
|
|
||||||
this.hasSomeObject = has;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyObject getSomeObject() {
|
|
||||||
return someObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeObject(MyObject someObject) {
|
|
||||||
this.someObject = someObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSomePrimitiveDouble() {
|
public boolean hasSomePrimitiveDouble() {
|
||||||
return hasPrimitiveSomeDouble;
|
return hasPrimitiveSomeDouble;
|
||||||
@ -91,38 +69,6 @@ public class Source {
|
|||||||
this.someInteger = someInteger;
|
this.someInteger = someInteger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasSomeLong1() {
|
|
||||||
return hasSomeLong1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasSomeLong1(boolean hasSomeInLong) {
|
|
||||||
this.hasSomeLong1 = hasSomeInLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSomeLong2() {
|
|
||||||
return hasSomeLong2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasSomeLong2(boolean hasSomeInLong) {
|
|
||||||
this.hasSomeLong2 = hasSomeInLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getSomeLong1() {
|
|
||||||
return someLong1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getSomeLong2() {
|
|
||||||
return someLong2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeLong1(Long someLong) {
|
|
||||||
this.someLong1 = someLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeLong2(Long someLong) {
|
|
||||||
this.someLong2 = someLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSomeList() {
|
public boolean hasSomeList() {
|
||||||
return hasSomeList;
|
return hasSomeList;
|
||||||
}
|
}
|
||||||
@ -138,4 +84,21 @@ public class Source {
|
|||||||
public void setSomeList(List<String> someList) {
|
public void setSomeList(List<String> someList) {
|
||||||
this.someList = someList;
|
this.someList = someList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getSomeArray() {
|
||||||
|
return someArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSomeArray(String[] someArray) {
|
||||||
|
this.someArray = someArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSomeArray() {
|
||||||
|
return hasSomeArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasSomeArray(boolean hasSomeArray) {
|
||||||
|
this.hasSomeArray = hasSomeArray;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2016 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||||
|
* and/or other contributors as indicated by the @authors tag. See the
|
||||||
|
* copyright.txt file in the distribution for a full listing of all
|
||||||
|
* contributors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.MappingTarget;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sean Huang
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public abstract class SourceTargetMapper {
|
||||||
|
|
||||||
|
public static final SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
|
||||||
|
|
||||||
|
//@Mapping( target = "someInteger2", source = "someNested.someInteger2" )
|
||||||
|
abstract Target sourceToTarget(Source source);
|
||||||
|
|
||||||
|
abstract void sourceToTarget(Source source, @MappingTarget Target target);
|
||||||
|
|
||||||
|
@Mappings( {
|
||||||
|
@Mapping(target = "somePrimitiveDouble", defaultValue = "111.1"),
|
||||||
|
@Mapping(target = "someInteger", defaultValue = "222"),
|
||||||
|
@Mapping(target = "someList", defaultValue = "a,b"),
|
||||||
|
@Mapping(target = "someArray", defaultValue = "u,v")
|
||||||
|
} )
|
||||||
|
abstract Target sourceToTargetWitDefaults(Source source);
|
||||||
|
|
||||||
|
|
||||||
|
protected List<String> toList( String in ) {
|
||||||
|
return Arrays.asList( in.split( "," ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] toArray( String in ) {
|
||||||
|
return in.split( "," );
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.presencecheck;
|
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -25,20 +25,10 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class Target {
|
public class Target {
|
||||||
|
|
||||||
private MyObject someObject;
|
|
||||||
private double somePrimitiveDouble;
|
private double somePrimitiveDouble;
|
||||||
private Integer someInteger;
|
private Integer someInteger;
|
||||||
private MyLongWrapper someLong1;
|
|
||||||
private MyLongWrapper someLong2;
|
|
||||||
private List<String> someList;
|
private List<String> someList;
|
||||||
|
private String[] someArray;
|
||||||
public MyObject getSomeObject() {
|
|
||||||
return someObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeObject(MyObject someObject) {
|
|
||||||
this.someObject = someObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getSomePrimitiveDouble() {
|
public double getSomePrimitiveDouble() {
|
||||||
return somePrimitiveDouble;
|
return somePrimitiveDouble;
|
||||||
@ -56,22 +46,6 @@ public class Target {
|
|||||||
this.someInteger = someInteger;
|
this.someInteger = someInteger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MyLongWrapper getSomeLong1() {
|
|
||||||
return someLong1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeLong1(MyLongWrapper someLong) {
|
|
||||||
this.someLong1 = someLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MyLongWrapper getSomeLong2() {
|
|
||||||
return someLong2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSomeLong2(MyLongWrapper someLong) {
|
|
||||||
this.someLong2 = someLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getSomeList() {
|
public List<String> getSomeList() {
|
||||||
return someList;
|
return someList;
|
||||||
}
|
}
|
||||||
@ -79,4 +53,13 @@ public class Target {
|
|||||||
public void setSomeList(List<String> someList) {
|
public void setSomeList(List<String> someList) {
|
||||||
this.someList = someList;
|
this.someList = someList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String[] getSomeArray() {
|
||||||
|
return someArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSomeArray(String[] someArray) {
|
||||||
|
this.someArray = someArray;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user