diff --git a/core-common/src/main/java/org/mapstruct/Mapper.java b/core-common/src/main/java/org/mapstruct/Mapper.java index 34bdf9ae7..d90636a0e 100644 --- a/core-common/src/main/java/org/mapstruct/Mapper.java +++ b/core-common/src/main/java/org/mapstruct/Mapper.java @@ -18,6 +18,8 @@ */ 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; @@ -148,4 +150,12 @@ public @interface Mapper { * specified with {@link #config()}. */ MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.EXPLICIT; + + /** + * Decide how to do presence check, such as checking null or calling hasX method, before mapping. + * Can be overridden by the one on {@link MapperConfig} or {@link Mapping}. + * + * @return strategy about how to do null or presence check + */ + SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL_INLINE; } diff --git a/core-common/src/main/java/org/mapstruct/MapperConfig.java b/core-common/src/main/java/org/mapstruct/MapperConfig.java index 1a471a1f7..96e2c93bb 100644 --- a/core-common/src/main/java/org/mapstruct/MapperConfig.java +++ b/core-common/src/main/java/org/mapstruct/MapperConfig.java @@ -18,6 +18,8 @@ */ 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; @@ -135,4 +137,12 @@ public @interface MapperConfig { */ MappingInheritanceStrategy mappingInheritanceStrategy() default MappingInheritanceStrategy.EXPLICIT; + + /** + * Decide how to do presence check, such as checking null or calling hasXXX method, before mapping. + * Can be overridden by the one on {@link Mapper} or {@link Mapping}. + * + * @return strategy about how to do null or presence check + */ + SourceValuePresenceCheckStrategy sourceValuePresenceCheckStrategy() default IS_NULL_INLINE; } diff --git a/core-common/src/main/java/org/mapstruct/SourceValuePresenceCheckStrategy.java b/core-common/src/main/java/org/mapstruct/SourceValuePresenceCheckStrategy.java new file mode 100644 index 000000000..6bf0092f3 --- /dev/null +++ b/core-common/src/main/java/org/mapstruct/SourceValuePresenceCheckStrategy.java @@ -0,0 +1,45 @@ +/** + * 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 to decide how to check null or hasX method before mapping + * + * @author Sean Huang + */ +public enum SourceValuePresenceCheckStrategy { + + /** + * 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; +} diff --git a/core-jdk8/src/main/java/org/mapstruct/Mapping.java b/core-jdk8/src/main/java/org/mapstruct/Mapping.java index ff217389c..e02146ace 100644 --- a/core-jdk8/src/main/java/org/mapstruct/Mapping.java +++ b/core-jdk8/src/main/java/org/mapstruct/Mapping.java @@ -18,6 +18,8 @@ */ 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; @@ -191,4 +193,12 @@ 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; } diff --git a/core/src/main/java/org/mapstruct/Mapping.java b/core/src/main/java/org/mapstruct/Mapping.java index 4a902fe70..430d5d345 100644 --- a/core/src/main/java/org/mapstruct/Mapping.java +++ b/core/src/main/java/org/mapstruct/Mapping.java @@ -18,6 +18,8 @@ */ 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; @@ -190,4 +192,12 @@ 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; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java index 337183c74..3f7efde85 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/BeanMappingMethod.java @@ -367,9 +367,6 @@ public class BeanMappingMethod extends MappingMethod { Iterator> targetPropertiesIterator = unprocessedTargetProperties.entrySet().iterator(); - // usually there should be only one getter; only for Boolean there may be two: isFoo() and getFoo() - List candidates = new ArrayList( 2 ); - while ( targetPropertiesIterator.hasNext() ) { Entry targetProperty = targetPropertiesIterator.next(); @@ -387,18 +384,24 @@ public class BeanMappingMethod extends MappingMethod { continue; } - PropertyMapping newPropertyMapping = null; - ExecutableElement sourceAccessor = sourceType.getPropertyReadAccessors().get( propertyName ); - if ( sourceAccessor != null ) { - Mapping mapping = method.getSingleMappingByTargetPropertyName( propertyName ); + + ExecutableElement sourceReadAccessor = + sourceParameter.getType().getPropertyReadAccessors().get( propertyName ); + + ExecutableElement sourcePresenceChecker = + sourceParameter.getType().getPropertyPresenceCheckers().get( propertyName ); + + if ( sourceReadAccessor != null ) { + Mapping mapping = method.getSingleMappingByTargetPropertyName( targetProperty.getKey() ); DeclaredType declaredSourceType = (DeclaredType) sourceParameter.getType().getTypeMirror(); SourceReference sourceRef = new SourceReference.BuilderFromProperty() .sourceParameter( sourceParameter ) - .type( ctx.getTypeFactory().getReturnType( declaredSourceType, sourceAccessor ) ) - .accessor( sourceAccessor ) - .name( propertyName ) + .type( ctx.getTypeFactory().getReturnType( declaredSourceType, sourceReadAccessor ) ) + .readAccessor( sourceReadAccessor ) + .presenceChecker( sourcePresenceChecker ) + .name( targetProperty.getKey() ) .build(); newPropertyMapping = new PropertyMappingBuilder() @@ -416,10 +419,7 @@ public class BeanMappingMethod extends MappingMethod { .build(); unprocessedSourceParameters.remove( sourceParameter ); - } - // candidates are handled - candidates.clear(); if ( propertyMapping != null && newPropertyMapping != null ) { // TODO improve error message diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java index d2814477b..9e4f3c172 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/NestedPropertyMappingMethod.java @@ -145,7 +145,7 @@ public class NestedPropertyMappingMethod extends MappingMethod { private final String safeName; public SafePropertyEntry( PropertyEntry entry, String safeName ) { - super( entry.getName(), entry.getAccessor(), entry.getType() ); + super( entry.getName(), entry.getAccessor(), entry.getPresenceChecker(), entry.getType() ); this.safeName = safeName; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java index 83f69409b..7159d6200 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java @@ -85,6 +85,7 @@ public class Type extends ModelElement implements Comparable { private final List enumConstants; private Map getters = null; + private Map presenceCheckers = null; private List allExecutables = null; private List setters = null; @@ -380,6 +381,23 @@ public class Type extends ModelElement implements Comparable { return getters; } + /** + * getPropertyPresenceCheckers + * + * @return an unmodifiable map of all presence checkers, indexed by property name + */ + public Map getPropertyPresenceCheckers() { + if ( presenceCheckers == null ) { + List checkerList = Filters.presenceCheckMethodsIn( getAllExecutables() ); + Map modifiableCheckers = new LinkedHashMap(); + for (ExecutableElement checker : checkerList) { + modifiableCheckers.put( Executables.getPropertyName( checker ), checker ); + } + presenceCheckers = Collections.unmodifiableMap( modifiableCheckers ); + } + return presenceCheckers; + } + /** * getPropertyWriteAccessors returns a map of the write accessors according to the CollectionMappingStrategy. These * accessors include: diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java index 6882ccd40..7f15a6241 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Mapping.java @@ -38,6 +38,7 @@ 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; @@ -61,6 +62,9 @@ public class Mapping { private final boolean isIgnored; private final List dependsOn; + private final SourceValuePresenceCheckStrategy valuePresenceCheckStrategy; + private final boolean isSetValuePresenceCheckStrategy; + private final AnnotationMirror mirror; private final AnnotationValue sourceAnnotationValue; private final AnnotationValue targetAnnotationValue; @@ -96,7 +100,6 @@ public class Mapping { public static Mapping fromMappingPrism(MappingPrism mappingPrism, ExecutableElement element, FormattingMessager messager) { - if ( mappingPrism.target().isEmpty() ) { messager.printMessage( element, @@ -139,13 +142,14 @@ public class Mapping { List dependsOn = mappingPrism.dependsOn() != null ? mappingPrism.dependsOn() : Collections.emptyList(); + boolean isSetValuePresenceCheckStrategy = mappingPrism.values.sourceValuePresenceCheckStrategy() != null; + + FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat ); SelectionParameters selectionParams = new SelectionParameters( mappingPrism.qualifiedBy(), mappingPrism.qualifiedByName(), resultTypeIsDefined ? mappingPrism.resultType() : null); - FormattingParameters formattingParam = new FormattingParameters( dateFormat, numberFormat ); - return new Mapping( source, constant, @@ -159,16 +163,20 @@ public class Mapping { formattingParam, selectionParams, mappingPrism.values.dependsOn(), - dependsOn + dependsOn, + SourceValuePresenceCheckStrategy.valueOf( mappingPrism.sourceValuePresenceCheckStrategy() ), + isSetValuePresenceCheckStrategy ); } @SuppressWarnings("checkstyle:parameternumber") - private Mapping(String sourceName, String constant, String javaExpression, String targetName, + private Mapping( String sourceName, String constant, String javaExpression, String targetName, String defaultValue, boolean isIgnored, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue, AnnotationValue targetAnnotationValue, FormattingParameters formattingParameters, SelectionParameters selectionParameters, - AnnotationValue dependsOnAnnotationValue, List dependsOn) { + AnnotationValue dependsOnAnnotationValue, List dependsOn, + SourceValuePresenceCheckStrategy valuePresenceCheckStrategy, + boolean isSetValuePresenceCheckStrategy ) { this.sourceName = sourceName; this.constant = constant; this.javaExpression = javaExpression; @@ -182,6 +190,8 @@ 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, @@ -282,6 +292,14 @@ 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 ); @@ -330,7 +348,9 @@ public class Mapping { formattingParameters, selectionParameters, dependsOnAnnotationValue, - Collections.emptyList() + Collections.emptyList(), + valuePresenceCheckStrategy, + isSetValuePresenceCheckStrategy ); reverse.init( method, messager, typeFactory ); @@ -357,7 +377,9 @@ public class Mapping { formattingParameters, selectionParameters, dependsOnAnnotationValue, - dependsOn + dependsOn, + valuePresenceCheckStrategy, + isSetValuePresenceCheckStrategy ); if ( sourceReference != null ) { @@ -375,3 +397,4 @@ public class Mapping { "\n}"; } } + diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceReference.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceReference.java index 364ee1b7a..eb0a9597c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceReference.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceReference.java @@ -175,12 +175,14 @@ public class SourceReference { for ( String entryName : entryNames ) { boolean matchFound = false; Map sourceReadAccessors = newType.getPropertyReadAccessors(); + Map sourcePresenceCheckers = newType.getPropertyPresenceCheckers(); + for ( Map.Entry getter : sourceReadAccessors.entrySet() ) { if ( getter.getKey().equals( entryName ) ) { - newType = typeFactory.getReturnType( - (DeclaredType) newType.getTypeMirror(), getter.getValue() - ); - sourceEntries.add( new PropertyEntry( entryName, getter.getValue(), newType ) ); + newType = typeFactory.getReturnType( (DeclaredType) newType.getTypeMirror(), + getter.getValue() ); + sourceEntries.add( new PropertyEntry( entryName, getter.getValue(), + sourcePresenceCheckers.get( entryName ), newType ) ); matchFound = true; break; } @@ -204,7 +206,8 @@ public class SourceReference { public static class BuilderFromProperty { private String name; - private ExecutableElement accessor; + private ExecutableElement readAccessor; + private ExecutableElement presenceChecker; private Type type; private Parameter sourceParameter; @@ -213,8 +216,13 @@ public class SourceReference { return this; } - public BuilderFromProperty accessor(ExecutableElement accessor) { - this.accessor = accessor; + public BuilderFromProperty readAccessor(ExecutableElement readAccessor) { + this.readAccessor = readAccessor; + return this; + } + + public BuilderFromProperty presenceChecker(ExecutableElement presenceChecker) { + this.presenceChecker = presenceChecker; return this; } @@ -230,8 +238,8 @@ public class SourceReference { public SourceReference build() { List sourcePropertyEntries = new ArrayList(); - if ( accessor != null ) { - sourcePropertyEntries.add( new PropertyEntry( name, accessor, type ) ); + if ( readAccessor != null ) { + sourcePropertyEntries.add( new PropertyEntry( name, readAccessor, presenceChecker, type ) ); } return new SourceReference( sourceParameter, sourcePropertyEntries, true ); } @@ -271,11 +279,14 @@ public class SourceReference { private final String name; private final ExecutableElement accessor; + private final ExecutableElement presenceChecker; private final Type type; - public PropertyEntry(String name, ExecutableElement accessor, Type type) { + public PropertyEntry(String name, ExecutableElement readAccessor, + ExecutableElement presenceChecker, Type type) { this.name = name; - this.accessor = accessor; + this.accessor = readAccessor; + this.presenceChecker = presenceChecker; this.type = type; } @@ -287,6 +298,10 @@ public class SourceReference { return accessor; } + public ExecutableElement getPresenceChecker() { + return presenceChecker; + } + public Type getType() { return type; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/naming/DefaultAccessorNamingStrategy.java b/processor/src/main/java/org/mapstruct/ap/internal/naming/DefaultAccessorNamingStrategy.java index f14e28c38..c04e703da 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/naming/DefaultAccessorNamingStrategy.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/naming/DefaultAccessorNamingStrategy.java @@ -43,6 +43,9 @@ 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; } @@ -67,6 +70,14 @@ 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(); @@ -81,8 +92,8 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy { @Override - public String getPropertyName(ExecutableElement getterOrSetterMethod) { - String methodName = getterOrSetterMethod.getSimpleName().toString(); + public String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) { + String methodName = getterOrHasserOrSetterMethod.getSimpleName().toString(); return Introspector.decapitalize( methodName.substring( methodName.startsWith( "is" ) ? 2 : 3 ) ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/prism/SourceValuePresenceCheckStrategy.java b/processor/src/main/java/org/mapstruct/ap/internal/prism/SourceValuePresenceCheckStrategy.java new file mode 100644 index 000000000..5f2425d89 --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/internal/prism/SourceValuePresenceCheckStrategy.java @@ -0,0 +1,45 @@ +/** + * 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.prism; + + +/** + * Prism for the enum {@link org.mapstruct.SourceValuePresenceCheckStrategy} + * + * @author Sean Huang + */ +public enum SourceValuePresenceCheckStrategy { + /** + * 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; +} diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java index d619ccf58..14a5d8e5d 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Executables.java @@ -76,6 +76,12 @@ public class Executables { ACCESSOR_NAMING_STRATEGY.getMethodType( method ) == MethodType.GETTER; } + public static boolean isPresenceCheckMethod(ExecutableElement method) { + return isPublic( method ) && + method.getParameters().isEmpty() && + ACCESSOR_NAMING_STRATEGY.getMethodType( method ) == MethodType.PRESENCE_CHECKER; + } + public static boolean isSetterMethod(ExecutableElement method) { return isPublic( method ) && method.getParameters().size() == 1 @@ -92,8 +98,8 @@ public class Executables { return method.getModifiers().contains( Modifier.PUBLIC ); } - public static String getPropertyName(ExecutableElement getterOrSetterMethod) { - return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrSetterMethod ); + public static String getPropertyName(ExecutableElement getterOrHasserOrSetterMethod) { + return ACCESSOR_NAMING_STRATEGY.getPropertyName( getterOrHasserOrSetterMethod ); } public static boolean isDefaultMethod(ExecutableElement method) { diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java index cc0c2478d..3894240e2 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java @@ -46,6 +46,18 @@ public class Filters { return getterMethods; } + public static List presenceCheckMethodsIn(Iterable elements) { + List presenceCheckMethods = new LinkedList(); + + for ( ExecutableElement method : elements ) { + if ( Executables.isPresenceCheckMethod( method ) ) { + presenceCheckMethods.add( method ); + } + } + + return presenceCheckMethods; + } + public static List setterMethodsIn(Iterable elements) { List setterMethods = new LinkedList(); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/MapperConfiguration.java b/processor/src/main/java/org/mapstruct/ap/internal/util/MapperConfiguration.java index 50b7c6b05..e4420b02a 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/MapperConfiguration.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/MapperConfiguration.java @@ -32,6 +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; /** * Provides an aggregated view to the settings given via {@link org.mapstruct.Mapper} and @@ -183,4 +184,22 @@ public class MapperConfiguration { public AnnotationMirror getAnnotationMirror() { 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; + } + } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java index 71accec8f..ca8e51a2b 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/util/Message.java @@ -51,6 +51,7 @@ public enum Message { PROPERTYMAPPING_INVALID_PARAMETER_NAME( "Method has no parameter named \"%s\"." ), PROPERTYMAPPING_NO_PROPERTY_IN_PARAMETER( "The type of parameter \"%s\" has no property named \"%s\"." ), PROPERTYMAPPING_INVALID_PROPERTY_NAME( "No property named \"%s\" exists in source parameter(s)." ), + PROPERTYMAPPING_NO_PRESENCE_CHECKER_FOR_SOURCE_TYPE( "Using custom source value presence checking strategy, but no presence checker found for %s in source type." ), PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE( "No read accessor found for property \"%s\" in target type." ), CONSTANTMAPPING_MAPPING_NOT_FOUND( "Can't map \"%s %s\" to \"%s %s\"." ), diff --git a/processor/src/main/java/org/mapstruct/ap/spi/MethodType.java b/processor/src/main/java/org/mapstruct/ap/spi/MethodType.java index d37edc730..f0e62949a 100644 --- a/processor/src/main/java/org/mapstruct/ap/spi/MethodType.java +++ b/processor/src/main/java/org/mapstruct/ap/spi/MethodType.java @@ -43,5 +43,10 @@ public enum MethodType { /** * Any method which is neither a JavaBeans getter, setter nor an adder method. */ - OTHER; + OTHER, + + /** + * A method to check whether a property is present, e.g. {@code public String hasName()}. + */ + PRESENCE_CHECKER; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/CustomMapper.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/CustomMapper.java new file mode 100644 index 000000000..33b5fd04c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/CustomMapper.java @@ -0,0 +1,35 @@ +/** + * 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 org.mapstruct.Mapper; +import org.mapstruct.SourceValuePresenceCheckStrategy; + +/** + * @author Sean Huang + */ +@Mapper( sourceValuePresenceCheckStrategy = SourceValuePresenceCheckStrategy.IS_NULL_INLINE ) +public class CustomMapper { + + public MyLongWrapper toMyLongWrapperViaPrimitive(Long primitive) { + MyLongWrapper wrapper = new MyLongWrapper(); + wrapper.setMyLong( primitive ); + return wrapper; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyLongWrapper.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyLongWrapper.java new file mode 100644 index 000000000..8e28a9e7d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyLongWrapper.java @@ -0,0 +1,38 @@ +/** + * 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; + + +/** + * @author Sjaak Derksen + */ +public class MyLongWrapper { + + private Long myLong; + + public Long getMyLong() { + return myLong; + } + + public void setMyLong(Long myLong) { + myLong.longValue(); + this.myLong = myLong; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyObject.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyObject.java new file mode 100644 index 000000000..1f035b671 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/MyObject.java @@ -0,0 +1,34 @@ +/** + * 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; + +/** + * @author Sean Huang + */ +public class MyObject { + @Override + public boolean equals(Object object) { + return this == object; + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/PresenceCheckTest.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/PresenceCheckTest.java new file mode 100644 index 000000000..62204c863 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/PresenceCheckTest.java @@ -0,0 +1,171 @@ +/** + * 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 list = new ArrayList(); + 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 list = new ArrayList(); + 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 list = new ArrayList(); + 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 ) ); + } + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Source.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Source.java new file mode 100644 index 000000000..00e52ef03 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Source.java @@ -0,0 +1,141 @@ +/** + * 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.List; + +/** + * @author Sean Huang + */ +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 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; + } + + public boolean hasSomePrimitiveDouble() { + return hasPrimitiveSomeDouble; + } + + public void setHasSomePrimitiveDouble(boolean has) { + this.hasPrimitiveSomeDouble = has; + } + + public double getSomePrimitiveDouble() { + return somePrimitiveDouble; + } + + public void setSomePrimitiveDouble(double someDouble) { + this.somePrimitiveDouble = someDouble; + } + + public boolean hasSomeInteger() { + return hasSomeInteger; + } + + public void setHasSomeInteger(boolean hasSomeInteger) { + this.hasSomeInteger = hasSomeInteger; + } + + public Integer getSomeInteger() { + return someInteger; + } + + public void setSomeInteger(Integer 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() { + return hasSomeList; + } + + public void setHasSomeList(boolean has) { + this.hasSomeList = has; + } + + public List getSomeList() { + return someList; + } + + public void setSomeList(List someList) { + this.someList = someList; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceTargetMapper.java new file mode 100644 index 000000000..2febd1f0e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceTargetMapper.java @@ -0,0 +1,82 @@ +/** + * 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); + */ +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceWtCheck.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceWtCheck.java new file mode 100644 index 000000000..f21de82ff --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/SourceWtCheck.java @@ -0,0 +1,45 @@ +/** + * 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; + + +/** + * @author Sean Huang + */ +public class SourceWtCheck extends Source { + + private int noCheckPrimitive; + private String noCheckObject; + + public int getNoCheckPrimitive() { + return noCheckPrimitive; + } + + public void setNoCheckPrimitive(int noCheckPrimitive) { + this.noCheckPrimitive = noCheckPrimitive; + } + + public String getNoCheckObject() { + return noCheckObject; + } + + public void setNoCheckObject(String noCheckObject) { + this.noCheckObject = noCheckObject; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Target.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Target.java new file mode 100644 index 000000000..9d54e6d42 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/Target.java @@ -0,0 +1,82 @@ +/** + * 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.List; + +/** + * @author Sean Huang + */ +public class Target { + + private MyObject someObject; + private double somePrimitiveDouble; + private Integer someInteger; + private MyLongWrapper someLong1; + private MyLongWrapper someLong2; + private List someList; + + public MyObject getSomeObject() { + return someObject; + } + + public void setSomeObject(MyObject someObject) { + this.someObject = someObject; + } + + public double getSomePrimitiveDouble() { + return somePrimitiveDouble; + } + + public void setSomePrimitiveDouble(double someDouble) { + this.somePrimitiveDouble = someDouble; + } + + public Integer getSomeInteger() { + return someInteger; + } + + public void setSomeInteger(Integer 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 getSomeList() { + return someList; + } + + public void setSomeList(List someList) { + this.someList = someList; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/presencecheck/TargetWtCheck.java b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/TargetWtCheck.java new file mode 100644 index 000000000..c644e221d --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/presencecheck/TargetWtCheck.java @@ -0,0 +1,45 @@ +/** + * 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; + + +/** + * @author Sean Huang + */ +public class TargetWtCheck extends Target { + + private int noCheckPrimitive; + private String noCheckObject; + + public int getNoCheckPrimitive() { + return noCheckPrimitive; + } + + public void setNoCheckPrimitive(int noCheckPrimitive) { + this.noCheckPrimitive = noCheckPrimitive; + } + + public String getNoCheckObject() { + return noCheckObject; + } + + public void setNoCheckObject(String noCheckObject) { + this.noCheckObject = noCheckObject; + } +}