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
|
||||
Sebastian Hasait
|
||||
Sjaak Derksen
|
||||
Sean Huang
|
||||
Timo Eckhardt
|
||||
Tomek Gubala
|
||||
Vincent Alexander Beelte
|
||||
|
@ -18,14 +18,13 @@
|
||||
*/
|
||||
package org.mapstruct;
|
||||
|
||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
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
|
||||
@ -152,10 +151,11 @@ public @interface Mapper {
|
||||
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}.
|
||||
*
|
||||
* @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;
|
||||
|
||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
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
|
||||
@ -139,10 +138,11 @@ public @interface MapperConfig {
|
||||
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}.
|
||||
*
|
||||
* @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;
|
||||
|
||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
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}.
|
||||
*/
|
||||
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;
|
||||
|
||||
import static org.mapstruct.SourceValuePresenceCheckStrategy.IS_NULL_INLINE;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.ElementType;
|
||||
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}.
|
||||
*/
|
||||
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() ) {
|
||||
|
||||
Entry<String, ExecutableElement> targetProperty = targetPropertiesIterator.next();
|
||||
String propertyName = targetProperty.getKey();
|
||||
String targetPropertyName = targetProperty.getKey();
|
||||
|
||||
PropertyMapping propertyMapping = null;
|
||||
|
||||
@ -387,10 +387,10 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
PropertyMapping newPropertyMapping = null;
|
||||
|
||||
ExecutableElement sourceReadAccessor =
|
||||
sourceParameter.getType().getPropertyReadAccessors().get( propertyName );
|
||||
sourceParameter.getType().getPropertyReadAccessors().get( targetPropertyName );
|
||||
|
||||
ExecutableElement sourcePresenceChecker =
|
||||
sourceParameter.getType().getPropertyPresenceCheckers().get( propertyName );
|
||||
sourceParameter.getType().getPropertyPresenceCheckers().get( targetPropertyName );
|
||||
|
||||
if ( sourceReadAccessor != null ) {
|
||||
Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() );
|
||||
@ -408,8 +408,8 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
.mappingContext( ctx )
|
||||
.sourceMethod( method )
|
||||
.targetWriteAccessor( targetProperty.getValue() )
|
||||
.targetReadAccessor( getTargetPropertyReadAccessor( propertyName ) )
|
||||
.targetPropertyName( propertyName )
|
||||
.targetReadAccessor( getTargetPropertyReadAccessor( targetPropertyName ) )
|
||||
.targetPropertyName( targetPropertyName )
|
||||
.sourceReference( sourceRef )
|
||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
||||
@ -426,7 +426,7 @@ public class BeanMappingMethod extends MappingMethod {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
Message.BEANMAPPING_SEVERAL_POSSIBLE_SOURCES,
|
||||
propertyName
|
||||
targetPropertyName
|
||||
);
|
||||
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.TYPE_CONVERTED;
|
||||
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.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.SourceReference;
|
||||
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.MapperConfiguration;
|
||||
import org.mapstruct.ap.internal.util.Message;
|
||||
@ -235,23 +237,14 @@ public class PropertyMapping extends ModelElement {
|
||||
|
||||
if ( assignment != null ) {
|
||||
if ( targetType.isCollectionOrMapType() ) {
|
||||
assignment = assignCollection( targetType, targetWriteAccessorType, assignment );
|
||||
assignment = assignToCollection( targetType, targetWriteAccessorType, assignment );
|
||||
}
|
||||
else if ( targetType.isArrayType() && sourceType.isArrayType() && assignment.getType() == DIRECT ) {
|
||||
Type arrayType = ctx.getTypeFactory().getType( Arrays.class );
|
||||
assignment = new ArrayCopyWrapper(
|
||||
assignment,
|
||||
targetPropertyName,
|
||||
arrayType,
|
||||
targetType,
|
||||
existingVariableNames
|
||||
);
|
||||
assignment = new NullCheckWrapper( assignment );
|
||||
assignment = assignToArray( targetType, assignment );
|
||||
}
|
||||
else {
|
||||
assignment = assignObject( sourceType, targetType, targetWriteAccessorType, assignment );
|
||||
assignment = assignToPlain( sourceType, targetType, targetWriteAccessorType, assignment );
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
ctx.getMessager().printMessage(
|
||||
@ -278,7 +271,9 @@ public class PropertyMapping extends ModelElement {
|
||||
}
|
||||
|
||||
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()
|
||||
.constantExpression( '"' + defaultValue + '"' )
|
||||
.formattingParameters( formattingParameters )
|
||||
@ -296,63 +291,98 @@ public class PropertyMapping extends ModelElement {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Assignment assignObject(Type sourceType, Type targetType, TargetWriteAccessorType targetAccessorType,
|
||||
Assignment rhs) {
|
||||
private Assignment assignToPlain(Type sourceType, Type targetType, TargetWriteAccessorType targetAccessorType,
|
||||
Assignment rightHandSide) {
|
||||
|
||||
Assignment result = rhs;
|
||||
Assignment result;
|
||||
|
||||
if ( targetAccessorType == TargetWriteAccessorType.SETTER ) {
|
||||
if ( result.isUpdateMethod() ) {
|
||||
if ( targetReadAccessor == null ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE,
|
||||
targetPropertyName );
|
||||
}
|
||||
Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
|
||||
result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod,
|
||||
targetType );
|
||||
}
|
||||
else {
|
||||
result = new SetterWrapper( result, method.getThrownTypes() );
|
||||
}
|
||||
if ( !sourceType.isPrimitive()
|
||||
&& !sourceReference.getPropertyEntries().isEmpty() ) { // parameter null taken care of by beanmapper
|
||||
|
||||
if ( result.isUpdateMethod() ) {
|
||||
result = new UpdateNullCheckWrapper( result );
|
||||
}
|
||||
else if ( result.getType() == TYPE_CONVERTED
|
||||
|| result.getType() == TYPE_CONVERTED_MAPPED
|
||||
|| result.getType() == MAPPED_TYPE_CONVERTED
|
||||
|| ( result.getType() == DIRECT && targetType.isPrimitive() ) ) {
|
||||
// for primitive types null check is not possible at all, but a conversion needs
|
||||
// a null check.
|
||||
result = new NullCheckWrapper( result );
|
||||
}
|
||||
}
|
||||
result = assignToPlainViaSetter( sourceType, targetType, rightHandSide );
|
||||
}
|
||||
else {
|
||||
// TargetAccessorType must be ADDER
|
||||
if ( getSourceType().isCollectionType() ) {
|
||||
result = new AdderWrapper(
|
||||
result,
|
||||
method.getThrownTypes(),
|
||||
getSourceRef(),
|
||||
sourceType
|
||||
);
|
||||
result = new NullCheckWrapper( result );
|
||||
}
|
||||
else {
|
||||
// Possibly adding null to a target collection. So should be surrounded by an null check.
|
||||
result = new SetterWrapper( result, method.getThrownTypes() );
|
||||
result = new NullCheckWrapper( result );
|
||||
}
|
||||
result = assignToPlainViaAdder( sourceType, rightHandSide );
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private Assignment assignCollection(Type targetType,
|
||||
private Assignment assignToPlainViaSetter(Type sourceType, Type targetType, Assignment rightHandSide) {
|
||||
|
||||
Assignment result;
|
||||
|
||||
if ( rightHandSide.isUpdateMethod() ) {
|
||||
if ( targetReadAccessor == null ) {
|
||||
ctx.getMessager().printMessage( method.getExecutable(),
|
||||
Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE,
|
||||
targetPropertyName );
|
||||
}
|
||||
Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null );
|
||||
result = new UpdateWrapper( rightHandSide, method.getThrownTypes(), factoryMethod,
|
||||
targetType );
|
||||
}
|
||||
else {
|
||||
result = new SetterWrapper( rightHandSide, method.getThrownTypes() );
|
||||
}
|
||||
|
||||
// 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() ) {
|
||||
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
|
||||
|| result.getType() == TYPE_CONVERTED_MAPPED
|
||||
|| result.getType() == MAPPED_TYPE_CONVERTED
|
||||
|| (result.getType() == DIRECT && targetType.isPrimitive()) ) {
|
||||
// for primitive types null check is not possible at all, but a conversion needs
|
||||
// a null check.
|
||||
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private Assignment assignToPlainViaAdder(Type sourceType, Assignment rightHandSide) {
|
||||
|
||||
Assignment result = rightHandSide;
|
||||
|
||||
if ( getSourceType().isCollectionType() ) {
|
||||
result = new AdderWrapper(
|
||||
result,
|
||||
method.getThrownTypes(),
|
||||
getSourceRef(),
|
||||
sourceType
|
||||
);
|
||||
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||
}
|
||||
else {
|
||||
// Possibly adding null to a target collection. So should be surrounded by an null check.
|
||||
result = new SetterWrapper( result, method.getThrownTypes() );
|
||||
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Assignment assignToCollection(Type targetType,
|
||||
TargetWriteAccessorType targetAccessorType,
|
||||
Assignment rhs) {
|
||||
|
||||
@ -419,15 +449,28 @@ public class PropertyMapping extends ModelElement {
|
||||
// for mapping methods (builtin / custom), the mapping method is responsible for the
|
||||
// null check. Typeconversions do not apply to collections and maps.
|
||||
if ( result.getType() == DIRECT ) {
|
||||
result = new NullCheckWrapper( result );
|
||||
result = new NullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||
}
|
||||
else if ( result.getType() == MAPPED && result.isUpdateMethod() ) {
|
||||
result = new UpdateNullCheckWrapper( result );
|
||||
result = new UpdateNullCheckWrapper( result, getSourcePresenceCheckerRef() );
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
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,
|
||||
ExecutableElement element) {
|
||||
|
||||
|
@ -25,7 +25,15 @@ package org.mapstruct.ap.internal.model.assignment;
|
||||
*/
|
||||
public class NullCheckWrapper extends AssignmentWrapper {
|
||||
|
||||
public NullCheckWrapper( Assignment decoratedAssignment ) {
|
||||
private final String sourcePresenceChecker;
|
||||
|
||||
|
||||
public NullCheckWrapper( Assignment decoratedAssignment, String sourcePresenceChecker ) {
|
||||
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 UpdateNullCheckWrapper( Assignment decoratedAssignment ) {
|
||||
private final String sourcePresenceChecker;
|
||||
|
||||
public UpdateNullCheckWrapper( Assignment decoratedAssignment, String sourcePresenceChecker ) {
|
||||
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.MappingPrism;
|
||||
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.Message;
|
||||
|
||||
@ -62,9 +61,6 @@ public class Mapping {
|
||||
private final boolean isIgnored;
|
||||
private final List<String> dependsOn;
|
||||
|
||||
private final SourceValuePresenceCheckStrategy valuePresenceCheckStrategy;
|
||||
private final boolean isSetValuePresenceCheckStrategy;
|
||||
|
||||
private final AnnotationMirror mirror;
|
||||
private final AnnotationValue sourceAnnotationValue;
|
||||
private final AnnotationValue targetAnnotationValue;
|
||||
@ -142,7 +138,6 @@ public class Mapping {
|
||||
List<String> dependsOn =
|
||||
mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.<String>emptyList();
|
||||
|
||||
boolean isSetValuePresenceCheckStrategy = mappingPrism.values.sourceValuePresenceCheckStrategy() != null;
|
||||
|
||||
FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat );
|
||||
SelectionParameters selectionParams = new SelectionParameters(
|
||||
@ -163,9 +158,7 @@ public class Mapping {
|
||||
formattingParam,
|
||||
selectionParams,
|
||||
mappingPrism.values.dependsOn(),
|
||||
dependsOn,
|
||||
SourceValuePresenceCheckStrategy.valueOf( mappingPrism.sourceValuePresenceCheckStrategy() ),
|
||||
isSetValuePresenceCheckStrategy
|
||||
dependsOn
|
||||
);
|
||||
}
|
||||
|
||||
@ -174,9 +167,7 @@ public class Mapping {
|
||||
String defaultValue, boolean isIgnored, AnnotationMirror mirror,
|
||||
AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue,
|
||||
FormattingParameters formattingParameters, SelectionParameters selectionParameters,
|
||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn,
|
||||
SourceValuePresenceCheckStrategy valuePresenceCheckStrategy,
|
||||
boolean isSetValuePresenceCheckStrategy ) {
|
||||
AnnotationValue dependsOnAnnotationValue, List<String> dependsOn ) {
|
||||
this.sourceName = sourceName;
|
||||
this.constant = constant;
|
||||
this.javaExpression = javaExpression;
|
||||
@ -190,8 +181,6 @@ public class Mapping {
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.dependsOnAnnotationValue = dependsOnAnnotationValue;
|
||||
this.dependsOn = dependsOn;
|
||||
this.valuePresenceCheckStrategy = valuePresenceCheckStrategy;
|
||||
this.isSetValuePresenceCheckStrategy = isSetValuePresenceCheckStrategy;
|
||||
}
|
||||
|
||||
private static String getExpression(MappingPrism mappingPrism, ExecutableElement element,
|
||||
@ -292,14 +281,6 @@ public class Mapping {
|
||||
return dependsOn;
|
||||
}
|
||||
|
||||
public SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() {
|
||||
return valuePresenceCheckStrategy;
|
||||
}
|
||||
|
||||
public boolean isSetSourceValuePresenceCheckStrategy() {
|
||||
return isSetValuePresenceCheckStrategy;
|
||||
}
|
||||
|
||||
private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
|
||||
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
|
||||
return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name );
|
||||
@ -348,9 +329,7 @@ public class Mapping {
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
Collections.<String>emptyList(),
|
||||
valuePresenceCheckStrategy,
|
||||
isSetValuePresenceCheckStrategy
|
||||
Collections.<String>emptyList()
|
||||
);
|
||||
|
||||
reverse.init( method, messager, typeFactory );
|
||||
@ -377,9 +356,7 @@ public class Mapping {
|
||||
formattingParameters,
|
||||
selectionParameters,
|
||||
dependsOnAnnotationValue,
|
||||
dependsOn,
|
||||
valuePresenceCheckStrategy,
|
||||
isSetValuePresenceCheckStrategy
|
||||
dependsOn
|
||||
);
|
||||
|
||||
if ( sourceReference != null ) {
|
||||
|
@ -283,7 +283,7 @@ public class SourceReference {
|
||||
private final Type type;
|
||||
|
||||
public PropertyEntry(String name, ExecutableElement readAccessor,
|
||||
ExecutableElement presenceChecker, Type type) {
|
||||
ExecutableElement presenceChecker, Type type) {
|
||||
this.name = name;
|
||||
this.accessor = readAccessor;
|
||||
this.presenceChecker = presenceChecker;
|
||||
|
@ -16,19 +16,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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
|
||||
*/
|
||||
public class MyObject {
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
return this == object;
|
||||
}
|
||||
public enum NullValueCheckStrategy {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
ON_IMPLICIT_CONVERSION,
|
||||
ALLWAYS;
|
||||
}
|
@ -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.util.Elements;
|
||||
|
||||
import org.mapstruct.ap.internal.naming.DefaultAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.internal.prism.AfterMappingPrism;
|
||||
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.DefaultAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.MethodType;
|
||||
|
||||
/**
|
||||
@ -63,8 +62,7 @@ public class Executables {
|
||||
}
|
||||
|
||||
private static final AccessorNamingStrategy ACCESSOR_NAMING_STRATEGY = Services.get(
|
||||
AccessorNamingStrategy.class,
|
||||
new DefaultAccessorNamingStrategy()
|
||||
AccessorNamingStrategy.class, new DefaultAccessorNamingStrategy()
|
||||
);
|
||||
|
||||
private Executables() {
|
||||
@ -98,8 +96,8 @@ public class Executables {
|
||||
return method.getModifiers().contains( Modifier.PUBLIC );
|
||||
}
|
||||
|
||||
public static String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) {
|
||||
return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrHasserOrSetterMethod );
|
||||
public static String getPropertyName(ExecutableElement getterOrPresenceCheckerOrSetterMethod) {
|
||||
return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrPresenceCheckerOrSetterMethod );
|
||||
}
|
||||
|
||||
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.MappingInheritanceStrategyPrism;
|
||||
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
|
||||
@ -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) {
|
||||
|
||||
// check on method level
|
||||
@ -185,21 +194,4 @@ public class MapperConfiguration {
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.internal.naming;
|
||||
package org.mapstruct.ap.spi;
|
||||
|
||||
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.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.
|
||||
@ -43,9 +41,6 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
if ( isGetterMethod( method ) ) {
|
||||
return MethodType.GETTER;
|
||||
}
|
||||
else if ( isPresenceCheckMethod( method ) ) {
|
||||
return MethodType.PRESENCE_CHECKER;
|
||||
}
|
||||
else if ( isSetterMethod( method ) ) {
|
||||
return MethodType.SETTER;
|
||||
}
|
||||
@ -70,14 +65,6 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
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) {
|
||||
String methodName = method.getSimpleName().toString();
|
||||
|
||||
@ -92,8 +79,8 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
|
||||
|
||||
@Override
|
||||
public String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) {
|
||||
String methodName = getterOrHasserOrSetterMethod.getSimpleName().toString();
|
||||
public String getPropertyName(ExecutableElement getterOrSetterMethod) {
|
||||
String methodName = getterOrSetterMethod.getSimpleName().toString();
|
||||
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 );
|
||||
}
|
||||
|
||||
private static String getQualifiedName(TypeMirror type) {
|
||||
protected static String getQualifiedName(TypeMirror type) {
|
||||
DeclaredType declaredType = type.accept(
|
||||
new SimpleTypeVisitor6<DeclaredType, Void>() {
|
||||
@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 ) {
|
||||
return ${returnType.null};
|
||||
}
|
||||
<#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>;
|
||||
<#list propertyEntries as entry>
|
||||
<#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.name} == null ) {
|
||||
return ${returnType.null};
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
<#if !entry_has_next>
|
||||
return ${entry.name};
|
||||
</#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.
|
||||
|
||||
-->
|
||||
if ( ${sourceReference} != null ) {
|
||||
if ( <#if sourcePresenceChecker?? >${sourcePresenceChecker}<#else>${sourceReference} != null</#if> ) {
|
||||
<@includeModel object=assignment
|
||||
targetBeanName=ext.targetBeanName
|
||||
existingInstanceMapping=ext.existingInstanceMapping
|
||||
|
@ -18,7 +18,7 @@
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
if ( ${sourceReference} != null ) {
|
||||
if ( <#if sourcePresenceChecker?? >${sourcePresenceChecker}<#else>${sourceReference} != null</#if> ) {
|
||||
<@includeModel object=assignment
|
||||
targetBeanName=ext.targetBeanName
|
||||
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
|
||||
* 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
|
||||
* 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;
|
||||
private String noCheckObject;
|
||||
public static final RockFestivalMapperWithConfig INSTANCE =
|
||||
Mappers.getMapper( RockFestivalMapperWithConfig.class );
|
||||
|
||||
public int getNoCheckPrimitive() {
|
||||
return noCheckPrimitive;
|
||||
@Mapping( target = "stage", source = "artistName" )
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.presencecheck;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.SourceValuePresenceCheckStrategy;
|
||||
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||
|
||||
/**
|
||||
* @author Sean Huang
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
@Mapper( sourceValuePresenceCheckStrategy = SourceValuePresenceCheckStrategy.IS_NULL_INLINE )
|
||||
public class CustomMapper {
|
||||
public class RockFestivalSource {
|
||||
|
||||
public MyLongWrapper toMyLongWrapperViaPrimitive(Long primitive) {
|
||||
MyLongWrapper wrapper = new MyLongWrapper();
|
||||
wrapper.setMyLong( primitive );
|
||||
return wrapper;
|
||||
private String artistName;
|
||||
|
||||
public String getArtistName() {
|
||||
return artistName;
|
||||
}
|
||||
|
||||
public void setArtistName(String artistName) {
|
||||
this.artistName = artistName;
|
||||
}
|
||||
|
||||
}
|
@ -16,23 +16,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.presencecheck;
|
||||
|
||||
package org.mapstruct.ap.test.source.nullvaluecheckstrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sjaak Derksen
|
||||
*/
|
||||
public class MyLongWrapper {
|
||||
public class RockFestivalTarget {
|
||||
|
||||
private Long myLong;
|
||||
private Stage stage;
|
||||
|
||||
public Long getMyLong() {
|
||||
return myLong;
|
||||
public Stage getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
public void setMyLong(Long myLong) {
|
||||
myLong.longValue();
|
||||
this.myLong = myLong;
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
* 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 noCheckObject;
|
||||
private String name;
|
||||
private boolean hasName = true;
|
||||
|
||||
public int getNoCheckPrimitive() {
|
||||
return noCheckPrimitive;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setNoCheckPrimitive(int noCheckPrimitive) {
|
||||
this.noCheckPrimitive = noCheckPrimitive;
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getNoCheckObject() {
|
||||
return noCheckObject;
|
||||
public boolean hasName() {
|
||||
return hasName;
|
||||
}
|
||||
|
||||
public void setNoCheckObject(String noCheckObject) {
|
||||
this.noCheckObject = noCheckObject;
|
||||
public void setHasName(boolean hasName) {
|
||||
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
|
||||
* 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 {
|
||||
/**
|
||||
* Only check != null for inline conversions
|
||||
*
|
||||
*/
|
||||
IS_NULL_INLINE,
|
||||
@Mapper( collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED )
|
||||
public interface SoccerTeamMapper {
|
||||
|
||||
/**
|
||||
* Always check != null, no matter whether it's an inline or method conversion
|
||||
*
|
||||
*/
|
||||
IS_NULL,
|
||||
SoccerTeamMapper INSTANCE = Mappers.getMapper( SoccerTeamMapper.class );
|
||||
|
||||
@Mapping( target = "goalKeeperName", ignore = true )
|
||||
SoccerTeamTarget mapAdder( SoccerTeamSource in );
|
||||
|
||||
|
||||
@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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.presencecheck;
|
||||
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -25,39 +25,17 @@ import java.util.List;
|
||||
*/
|
||||
public class Source {
|
||||
|
||||
private MyObject someObject;
|
||||
private boolean hasSomeObject = true;
|
||||
|
||||
private double somePrimitiveDouble;
|
||||
private boolean hasPrimitiveSomeDouble = true;
|
||||
|
||||
private Integer someInteger;
|
||||
private boolean hasSomeInteger = true;
|
||||
|
||||
private Long someLong1;
|
||||
private boolean hasSomeLong1 = true;
|
||||
|
||||
private Long someLong2;
|
||||
private boolean hasSomeLong2 = true;
|
||||
|
||||
private List<String> someList;
|
||||
private boolean hasSomeList = true;
|
||||
|
||||
public boolean hasSomeObject() {
|
||||
return hasSomeObject;
|
||||
}
|
||||
|
||||
public void setHasSomeObject(boolean has) {
|
||||
this.hasSomeObject = has;
|
||||
}
|
||||
|
||||
public MyObject getSomeObject() {
|
||||
return someObject;
|
||||
}
|
||||
|
||||
public void setSomeObject(MyObject someObject) {
|
||||
this.someObject = someObject;
|
||||
}
|
||||
private String[] someArray;
|
||||
private boolean hasSomeArray = true;
|
||||
|
||||
public boolean hasSomePrimitiveDouble() {
|
||||
return hasPrimitiveSomeDouble;
|
||||
@ -91,38 +69,6 @@ public class Source {
|
||||
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() {
|
||||
return hasSomeList;
|
||||
}
|
||||
@ -138,4 +84,21 @@ public class Source {
|
||||
public void setSomeList(List<String> 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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.test.presencecheck;
|
||||
package org.mapstruct.ap.test.source.presencecheck.spi;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -25,20 +25,10 @@ import java.util.List;
|
||||
*/
|
||||
public class Target {
|
||||
|
||||
private MyObject someObject;
|
||||
private double somePrimitiveDouble;
|
||||
private Integer someInteger;
|
||||
private MyLongWrapper someLong1;
|
||||
private MyLongWrapper someLong2;
|
||||
private List<String> someList;
|
||||
|
||||
public MyObject getSomeObject() {
|
||||
return someObject;
|
||||
}
|
||||
|
||||
public void setSomeObject(MyObject someObject) {
|
||||
this.someObject = someObject;
|
||||
}
|
||||
private String[] someArray;
|
||||
|
||||
public double getSomePrimitiveDouble() {
|
||||
return somePrimitiveDouble;
|
||||
@ -56,22 +46,6 @@ public class Target {
|
||||
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() {
|
||||
return someList;
|
||||
}
|
||||
@ -79,4 +53,13 @@ public class Target {
|
||||
public void setSomeList(List<String> 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