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 39e942965c..24add29d7b 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 @@ -111,7 +111,11 @@ private Builder setupMethodWithMapping(Method sourceMethod) { this.method = sourceMethod; this.methodMappings = sourceMethod.getMappingOptions().getMappings(); CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy(); - Map accessors = method.getResultType().getPropertyWriteAccessors( cms ); + Map srcReadAccessors = sourceMethod.getSourceReadAccessors(); + + Map accessors = method.getResultType().getPropertyWriteAccessors( cms, + ( srcReadAccessors ) ); + this.targetProperties = accessors.keySet(); this.unprocessedTargetProperties = new LinkedHashMap( accessors ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java index 8121f7def7..050ca38982 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/HelperMethod.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import javax.lang.model.element.ExecutableElement; @@ -34,6 +35,7 @@ import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods; import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.Strings; +import org.mapstruct.ap.internal.util.accessor.Accessor; /** * A non mapping method to be generated. @@ -265,4 +267,8 @@ public boolean isLifecycleCallbackMethod() { public boolean isUpdateMethod() { return false; // irrelevant } + + public Map getSourceReadAccessors() { + return Collections.emptyMap(); + } } 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 3be8057233..040088894d 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 @@ -437,6 +437,11 @@ public Map getPropertyPresenceCheckers() { return presenceCheckers; } + public Map getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) { + return getPropertyWriteAccessors( cmStrategy, Collections.emptyMap() ); + } + + /** * getPropertyWriteAccessors returns a map of the write accessors according to the CollectionMappingStrategy. These * accessors include: @@ -450,7 +455,8 @@ public Map getPropertyPresenceCheckers() { * @param cmStrategy collection mapping strategy * @return an unmodifiable map of all write accessors indexed by property name */ - public Map getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) { + public Map getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy, + Map sourceAccessor ) { // collect all candidate target accessors List candidates = new ArrayList( getSetters() ); candidates.addAll( getAlternativeTargetAccessors() ); @@ -461,8 +467,8 @@ public Map getPropertyWriteAccessors( CollectionMappingStrateg String targetPropertyName = Executables.getPropertyName( candidate ); Accessor readAccessor = getPropertyReadAccessors().get( targetPropertyName ); - - Type preferredType = determinePreferredType( readAccessor ); + Accessor sourceReadAccessor = sourceAccessor.get( targetPropertyName ); + TypeMirror preferredType = determinePreferredType( readAccessor, sourceReadAccessor ); Type targetType = determineTargetType( candidate ); // A target access is in general a setter method on the target object. However, in case of collections, @@ -496,8 +502,19 @@ else if ( Executables.isFieldAccessor( candidate ) && ( Executables.isFinal( can } Accessor previousCandidate = result.get( targetPropertyName ); - if ( previousCandidate == null || preferredType == null || ( targetType != null - && typeUtils.isAssignable( preferredType.getTypeMirror(), targetType.getTypeMirror() ) ) ) { + + + if (previousCandidate != null + && sourceAccessor != null + && sourceReadAccessor != null + && !isBetter( previousCandidate, candidate, + sourceReadAccessor.getAccessedType() ) ) { + continue; + } + + + if (previousCandidate == null || preferredType == null || (targetType != null + && typeUtils.isAssignable( preferredType, targetType.getTypeMirror() ) ) ) { result.put( targetPropertyName, candidate ); } } @@ -505,9 +522,40 @@ else if ( Executables.isFieldAccessor( candidate ) && ( Executables.isFinal( can return result; } - private Type determinePreferredType(Accessor readAccessor) { + private TypeMirror extractTypeMirror( Accessor accessor ) { + if ( accessor.getExecutable() == null ) { + return null; + } + return accessor.getExecutable().getParameters().get( 0 ).asType(); + } + + private boolean isBetter( Accessor previousCandidate, Accessor nextCandidate, TypeMirror preferredType ) { + TypeMirror previousType = extractTypeMirror( previousCandidate ); + TypeMirror nextType = extractTypeMirror( nextCandidate ); + if ( nextType == null ) { + return false; + } + + if (typeUtils.isSameType( previousType, preferredType )) { + return false; + } + + if (typeUtils.isSameType( nextType, preferredType )) { + return true; + } + if (typeUtils.isAssignable( nextType, preferredType ) + && !typeUtils.isAssignable( previousType, preferredType )) { + return true; + } + return false; + } + + private TypeMirror determinePreferredType(Accessor readAccessor, Accessor sourceReadAccessor) { + if ( sourceReadAccessor != null ) { + return sourceReadAccessor.getAccessedType(); + } if ( readAccessor != null ) { - return typeFactory.getReturnType( (DeclaredType) typeMirror, readAccessor ); + return typeFactory.getReturnType( (DeclaredType) typeMirror, readAccessor ).getTypeMirror(); } return null; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/ForgedMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/ForgedMethod.java index 97523a2a60..c023b379c5 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/ForgedMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/ForgedMethod.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.lang.model.element.ExecutableElement; @@ -29,6 +30,7 @@ import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.Strings; +import org.mapstruct.ap.internal.util.accessor.Accessor; /** * This method will be generated in absence of a suitable abstract method to implement. @@ -51,6 +53,7 @@ public class ForgedMethod implements Method { private final MappingOptions mappingOptions; private final ParameterProvidedMethods contextProvidedMethods; private final boolean forgedNameBased; + private final Map sourceReadAccessors; /** * Creates a new forged method with the given name. @@ -120,6 +123,7 @@ public ForgedMethod(String name, Type sourceType, Type returnType, MapperConfigu this.mappingOptions = mappingOptions == null ? MappingOptions.empty() : mappingOptions; this.mappingOptions.initWithParameter( sourceParameter ); this.forgedNameBased = forgedNameBased; + this.sourceReadAccessors = MappingMethodUtils.getSourceReadAccessors( getSourceParameters(), mappingOptions ); } /** @@ -143,6 +147,7 @@ public ForgedMethod(String name, ForgedMethod forgedMethod) { this.name = name; this.forgedNameBased = forgedMethod.forgedNameBased; + this.sourceReadAccessors = forgedMethod.sourceReadAccessors; } @Override @@ -321,6 +326,10 @@ public MappingOptions getMappingOptions() { return mappingOptions; } + public Map getSourceReadAccessors() { + return sourceReadAccessors; + } + @Override public boolean equals(Object o) { if ( this == o ) { 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 c225adc138..6b82b547c6 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 @@ -375,7 +375,8 @@ public List getDependsOn() { private boolean hasPropertyInReverseMethod(String name, SourceMethod method) { CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy(); - return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name ); + return method.getResultType().getPropertyWriteAccessors( cms, method.getSourceReadAccessors() ) + .containsKey( name ); } public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) { diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodUtils.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodUtils.java index d38451785a..a62b18865e 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodUtils.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/MappingMethodUtils.java @@ -18,6 +18,14 @@ */ package org.mapstruct.ap.internal.model.source; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.mapstruct.ap.internal.model.common.Parameter; +import org.mapstruct.ap.internal.util.accessor.Accessor; + import static org.mapstruct.ap.internal.util.Collections.first; /** @@ -45,4 +53,33 @@ public static boolean isEnumMapping(Method method) { && first( method.getSourceParameters() ).getType().isEnumType() && method.getResultType().isEnumType(); } + + public static Map getSourceReadAccessors(List sourceParameters, + MappingOptions mappingOptions) { + + if ( mappingOptions == null ) { + return Collections.emptyMap(); + } + + Map map = new LinkedHashMap(); + Map bindings = new LinkedHashMap(); + if ( mappingOptions.getMappings() != null ) { + for ( Map.Entry> entry : mappingOptions.getMappings().entrySet() ) { + if ( entry.getValue() != null && entry.getValue().size() > 0 ) { + bindings.put( entry.getKey(), entry.getValue().get( 0 ).getSourceName() ); + } + } + } + + for ( Parameter parameter : sourceParameters ) { + map.putAll( parameter.getType().getPropertyReadAccessors() ); + } + + for ( Map.Entry entry : bindings.entrySet() ) { + if ( map.get( entry.getValue() ) != null ) { + map.put( entry.getKey(), map.remove( entry.getValue() ) ); + } + } + return Collections.unmodifiableMap( map ); + } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Method.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Method.java index 9f93205a12..4fcb45370c 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/Method.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/Method.java @@ -19,6 +19,7 @@ package org.mapstruct.ap.internal.model.source; import java.util.List; +import java.util.Map; import javax.lang.model.element.ExecutableElement; @@ -27,6 +28,7 @@ import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod; import org.mapstruct.ap.internal.util.MapperConfiguration; +import org.mapstruct.ap.internal.util.accessor.Accessor; /** * This interface makes available common method properties and a matching method There are 2 known implementors: @@ -200,4 +202,11 @@ public interface Method { * @return the mapping options for this method */ MappingOptions getMappingOptions(); + + /** + * + * @return map of possible accessors + */ + + Map getSourceReadAccessors(); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java index 3c7142395b..2ececd1487 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/SourceMethod.java @@ -40,6 +40,7 @@ import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.Strings; +import org.mapstruct.ap.internal.util.accessor.Accessor; /** * Represents a mapping method with source and target type and the mappings between the properties of source and target @@ -72,8 +73,10 @@ public class SourceMethod implements Method { private final List sourceParameters; private final List contextParameters; private final ParameterProvidedMethods contextProvidedMethods; + private final Map sourceReadAccessors; private List parameterNames; + private Map getSourceReadAccessors; private List applicablePrototypeMethods; private List applicableReversePrototypeMethods; @@ -231,6 +234,7 @@ private SourceMethod(Builder builder, MappingOptions mappingOptions) { this.config = builder.mapperConfig; this.prototypeMethods = builder.prototypeMethods; this.mapperToImplement = builder.definingType; + this.sourceReadAccessors = MappingMethodUtils.getSourceReadAccessors( sourceParameters, mappingOptions ); } private boolean determineIfIsObjectFactory(ExecutableElement executable) { @@ -238,8 +242,8 @@ private boolean determineIfIsObjectFactory(ExecutableElement executable) { boolean hasNoSourceParameters = getSourceParameters().isEmpty(); boolean hasNoMappingTargetParam = getMappingTargetParameter() == null; return !isLifecycleCallbackMethod() && !returnType.isVoid() - && hasNoMappingTargetParam - && ( hasFactoryAnnotation || hasNoSourceParameters ); + && hasNoMappingTargetParam + && ( hasFactoryAnnotation || hasNoSourceParameters ); } @Override @@ -314,26 +318,26 @@ public Mapping getSingleMappingByTargetPropertyName(String targetPropertyName) { public boolean reverses(SourceMethod method) { return method.getDeclaringMapper() == null - && method.isAbstract() - && getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1 - && first( getSourceParameters() ).getType().isAssignableTo( method.getResultType() ) - && getResultType().isAssignableTo( first( method.getSourceParameters() ).getType() ); + && method.isAbstract() + && getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1 + && first( getSourceParameters() ).getType().isAssignableTo( method.getResultType() ) + && getResultType().isAssignableTo( first( method.getSourceParameters() ).getType() ); } public boolean isSame(SourceMethod method) { return getSourceParameters().size() == 1 && method.getSourceParameters().size() == 1 - && equals( first( getSourceParameters() ).getType(), first( method.getSourceParameters() ).getType() ) - && equals( getResultType(), method.getResultType() ); + && equals( first( getSourceParameters() ).getType(), first( method.getSourceParameters() ).getType() ) + && equals( getResultType(), method.getResultType() ); } public boolean canInheritFrom(SourceMethod method) { return method.getDeclaringMapper() == null - && method.isAbstract() - && isMapMapping() == method.isMapMapping() - && isIterableMapping() == method.isIterableMapping() - && isEnumMapping() == method.isEnumMapping() - && getResultType().isAssignableTo( method.getResultType() ) - && allParametersAreAssignable( getSourceParameters(), method.getSourceParameters() ); + && method.isAbstract() + && isMapMapping() == method.isMapMapping() + && isIterableMapping() == method.isIterableMapping() + && isEnumMapping() == method.isEnumMapping() + && getResultType().isAssignableTo( method.getResultType() ) + && allParametersAreAssignable( getSourceParameters(), method.getSourceParameters() ); } @Override @@ -354,8 +358,8 @@ public Parameter getTargetTypeParameter() { public boolean isIterableMapping() { if ( isIterableMapping == null ) { isIterableMapping = getSourceParameters().size() == 1 - && first( getSourceParameters() ).getType().isIterableType() - && getResultType().isIterableType(); + && first( getSourceParameters() ).getType().isIterableType() + && getResultType().isIterableType(); } return isIterableMapping; } @@ -363,7 +367,7 @@ && first( getSourceParameters() ).getType().isIterableType() public boolean isStreamMapping() { if ( isStreamMapping == null ) { isStreamMapping = getSourceParameters().size() == 1 - && ( first( getSourceParameters() ).getType().isIterableType() && getResultType().isStreamType() + && ( first( getSourceParameters() ).getType().isIterableType() && getResultType().isStreamType() || first( getSourceParameters() ).getType().isStreamType() && getResultType().isIterableType() || first( getSourceParameters() ).getType().isStreamType() && getResultType().isStreamType() ); } @@ -373,8 +377,8 @@ public boolean isStreamMapping() { public boolean isMapMapping() { if ( isMapMapping == null ) { isMapMapping = getSourceParameters().size() == 1 - && first( getSourceParameters() ).getType().isMapType() - && getResultType().isMapType(); + && first( getSourceParameters() ).getType().isMapType() + && getResultType().isMapType(); } return isMapMapping; } @@ -389,10 +393,10 @@ public boolean isEnumMapping() { public boolean isBeanMapping() { if ( isBeanMapping == null ) { isBeanMapping = !isIterableMapping() - && !isMapMapping() - && !isEnumMapping() - && !isValueMapping() - && !isStreamMapping(); + && !isMapMapping() + && !isEnumMapping() + && !isValueMapping() + && !isStreamMapping(); } return isBeanMapping; } @@ -412,7 +416,7 @@ public boolean isValueMapping() { } private boolean equals(Object o1, Object o2) { - return (o1 == null && o2 == null) || (o1 != null) && o1.equals( o2 ); + return ( o1 == null && o2 == null ) || ( o1 != null ) && o1.equals( o2 ); } @Override @@ -542,7 +546,6 @@ public boolean matches(List sourceTypes, Type targetType) { /** * @param parameters the parameter list to check - * * @return {@code true} if the parameter list contains a parameter annotated with {@code @TargetType} */ public static boolean containsTargetTypeParameter(List parameters) { @@ -610,4 +613,8 @@ public boolean isAbstract() { public boolean isUpdateMethod() { return getMappingTargetParameter() != null; } + + public Map getSourceReadAccessors() { + return sourceReadAccessors; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/TargetReference.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/TargetReference.java index 00487d23e6..a3f1453435 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/TargetReference.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/TargetReference.java @@ -141,7 +141,8 @@ private List getTargetEntries(Type type, String[] entryNames) { for ( int i = 0; i < entryNames.length; i++ ) { Accessor targetReadAccessor = nextType.getPropertyReadAccessors().get( entryNames[i] ); - Accessor targetWriteAccessor = nextType.getPropertyWriteAccessors( cms ).get( entryNames[i] ); + Accessor targetWriteAccessor = nextType.getPropertyWriteAccessors( cms, + method.getSourceReadAccessors() ).get( entryNames[i] ); if ( targetWriteAccessor == null || ( i < entryNames.length - 1 && targetReadAccessor == null) ) { // there should always be a write accessor and there should be read accessor mandatory for all // but the last diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java index 60c939c691..f6cd0b4824 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/source/builtin/BuiltInMethod.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import javax.lang.model.element.ExecutableElement; @@ -38,6 +39,7 @@ import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods; import org.mapstruct.ap.internal.util.MapperConfiguration; import org.mapstruct.ap.internal.util.Strings; +import org.mapstruct.ap.internal.util.accessor.Accessor; /** * Represents a "built-in" mapping method which will be added as private method to the generated mapper. Built-in @@ -288,4 +290,8 @@ public boolean isUpdateMethod() { public MappingOptions getMappingOptions() { return MappingOptions.empty(); } + + public Map getSourceReadAccessors() { + return Collections.emptyMap(); + } } 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 3b087b59c7..3d9069c8aa 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 @@ -203,7 +203,10 @@ public static List getAllEnclosedExecutableElements(Elements * * @return the executable elements usable in the type */ - public static List getAllEnclosedAccessors(Elements elementUtils, TypeElement element) { + public static List getAllEnclosedAccessors( Elements elementUtils, TypeElement element ) { + if (element == null) { + return java.util.Collections.emptyList(); + } List enclosedElements = new ArrayList(); element = replaceTypeElementIfNecessary( elementUtils, element ); addEnclosedElementsInHierarchy( elementUtils, enclosedElements, element, element ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingMapperConfig.java b/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingMapperConfig.java new file mode 100644 index 0000000000..2db231d652 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingMapperConfig.java @@ -0,0 +1,33 @@ +/** + * Copyright 2012-2017 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.overloading; + +import org.mapstruct.MapperConfig; +import org.mapstruct.Mapping; +import org.mapstruct.MappingInheritanceStrategy; +import org.mapstruct.ReportingPolicy; + +@MapperConfig(unmappedTargetPolicy = ReportingPolicy.ERROR, + mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG) +public interface OverloadingMapperConfig { + + @Mapping(target = "updatedOnTarget2", source = "updatedOn2") + Target sourceToTargetConfig( Source source ); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingTest.java b/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingTest.java new file mode 100644 index 0000000000..21425a33a2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/overloading/OverloadingTest.java @@ -0,0 +1,38 @@ +/** + * Copyright 2012-2017 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.overloading; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +@WithClasses({ + SourceTargetMapper.class, + Source.class, + Target.class, + OverloadingMapperConfig.class +}) +@RunWith(AnnotationProcessorTestRunner.class) +public class OverloadingTest { + + @Test + public void testShouldGenerateCorrectMapperImplementation() { + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/overloading/Source.java b/processor/src/test/java/org/mapstruct/ap/test/overloading/Source.java new file mode 100644 index 0000000000..dd67cc41b4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/overloading/Source.java @@ -0,0 +1,58 @@ +/** + * Copyright 2012-2017 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.overloading; + +import java.util.Date; + +public class Source { + + private Date updatedOn; + private Date updatedOn2; + + public Source(Date updatedOn) { + this.updatedOn = updatedOn; + } + + public Source() { + } + + public Date getUpdatedOn() { + return updatedOn; + } + + public void setUpdatedOn(Date updatedOn) { + this.updatedOn = updatedOn; + } + + public void setUpdatedOn(long updatedOn) { + this.updatedOn = new Date( updatedOn ); + } + + public Date getUpdatedOn2() { + return updatedOn2; + } + + public void setUpdatedOn2(Date updatedOn2) { + this.updatedOn2 = updatedOn2; + } + + public void setUpdatedOn2(long updatedOn) { + this.updatedOn2 = new Date( updatedOn ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/overloading/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/overloading/SourceTargetMapper.java new file mode 100644 index 0000000000..0143b5a06f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/overloading/SourceTargetMapper.java @@ -0,0 +1,39 @@ +/** + * Copyright 2012-2017 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.overloading; + +import org.mapstruct.InheritConfiguration; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Mapper(config = OverloadingMapperConfig.class) +public interface SourceTargetMapper { + + SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); + + @InheritConfiguration + @Mapping(target = "updatedOnTarget", source = "updatedOn") + Target sourceToTarget( Source source ); + + @InheritInverseConfiguration(name = "sourceToTarget") + Source targetToSourceReversed( Target source); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/overloading/Target.java b/processor/src/test/java/org/mapstruct/ap/test/overloading/Target.java new file mode 100644 index 0000000000..cdd940170a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/overloading/Target.java @@ -0,0 +1,57 @@ +/** + * Copyright 2012-2017 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.overloading; + +import java.util.Date; + +public class Target { + + private long updatedOnTarget; + private long updatedOnTarget2; + + public long getUpdatedOnTarget() { + return updatedOnTarget; + } + + public void setUpdatedOnTarget(long updatedOnTarget) { + this.updatedOnTarget = updatedOnTarget; + } + + public void setUpdatedOnTarget( Date updatedOn ) { + if (updatedOn == null) { + return; + } + this.updatedOnTarget = updatedOn.getTime(); + } + + public long getUpdatedOnTarget2() { + return updatedOnTarget2; + } + + public void setUpdatedOnTarget2(long updatedOnTarget2) { + this.updatedOnTarget2 = updatedOnTarget2; + } + + public void setUpdatedOnTarget2( Date updatedOn ) { + if (updatedOn == null) { + return; + } + this.updatedOnTarget2 = updatedOn.getTime(); + } +}