From 5457f3583ac5ffd7e62eafdccb904b4ab0b2cc49 Mon Sep 17 00:00:00 2001 From: sjaakd Date: Sun, 13 Jul 2014 21:02:41 +0200 Subject: [PATCH] #252 merging reverse mapping with forward mapping. Fixing reverse check in Mapping. --- .../org/mapstruct/ReverseMappingMethod.java | 48 ++++++ .../itest/simple/SourceTargetMapper.java | 2 + .../mapstruct/ap/prism/PrismGenerator.java | 2 + .../ap/processor/MapperCreationProcessor.java | 159 ++++++++++++++++-- .../collection/CollectionMappingTest.java | 4 +- .../test/collection/SourceTargetMapper.java | 15 +- .../collection/map/SourceTargetMapper.java | 5 +- .../mapstruct/ap/test/complex/CarMapper.java | 9 +- .../test/conversion/SourceTargetMapper.java | 3 +- .../conversion/date/SourceTargetMapper.java | 5 +- .../java8time/SourceTargetMapper.java | 6 + .../jodatime/JodaConversionTest.java | 2 +- .../jodatime/SourceTargetMapper.java | 3 + .../ap/test/ignore/AnimalMapper.java | 3 +- .../reverse/ReverseMappingMethodTest.java | 157 +++++++++++++++++ .../org/mapstruct/ap/test/reverse/Source.java | 68 ++++++++ .../ap/test/reverse/SourceTargetMapper.java | 57 +++++++ .../reverse/SourceTargetMapperAmbigious1.java | 57 +++++++ .../reverse/SourceTargetMapperAmbigious2.java | 57 +++++++ .../reverse/SourceTargetMapperAmbigious3.java | 58 +++++++ ...ourceTargetMapperErroneouslyAnnotated.java | 58 +++++++ .../SourceTargetMapperNonMatchingName.java | 50 ++++++ .../org/mapstruct/ap/test/reverse/Target.java | 58 +++++++ 23 files changed, 855 insertions(+), 31 deletions(-) create mode 100644 core-common/src/main/java/org/mapstruct/ReverseMappingMethod.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/ReverseMappingMethodTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/Source.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious1.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious2.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious3.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperErroneouslyAnnotated.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperNonMatchingName.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/reverse/Target.java diff --git a/core-common/src/main/java/org/mapstruct/ReverseMappingMethod.java b/core-common/src/main/java/org/mapstruct/ReverseMappingMethod.java new file mode 100644 index 000000000..5aa401524 --- /dev/null +++ b/core-common/src/main/java/org/mapstruct/ReverseMappingMethod.java @@ -0,0 +1,48 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation ensures that all forward mappings are copied as a base for the reverse mapping. + * + * MapStruct will check if there is a source / target mapper matching the profile. That is: + *
    + *
  1. the source parameter should match the return type (or the parameter indicated as {@link MappingTarget}
  2. + *
  3. the target parameter should match the source parameter
  4. + *
+ * + * @author Sjaak Derksen + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface ReverseMappingMethod { + + /** + * The name of the 'forward' mapping method that should be taken as the base. + * + * @return + */ + String configuredBy() default ""; + +} diff --git a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java index 513e0d20c..7b1bdcc5f 100644 --- a/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java +++ b/integrationtest/src/test/resources/simpleTest/src/main/java/org/mapstruct/itest/simple/SourceTargetMapper.java @@ -21,6 +21,7 @@ package org.mapstruct.itest.simple; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -34,5 +35,6 @@ public interface SourceTargetMapper { }) Target sourceToTarget(Source source); + @ReverseMappingMethod Source targetToSource(Target target); } diff --git a/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java b/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java index 0dbc9ef46..0437b0259 100644 --- a/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java +++ b/processor/src/main/java/org/mapstruct/ap/prism/PrismGenerator.java @@ -30,6 +30,7 @@ import org.mapstruct.MapperConfig; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.TargetType; /** @@ -47,6 +48,7 @@ import org.mapstruct.TargetType; @GeneratePrism(value = MappingTarget.class, publicAccess = true), @GeneratePrism(value = DecoratedWith.class, publicAccess = true), @GeneratePrism(value = MapperConfig.class, publicAccess = true), + @GeneratePrism(value = ReverseMappingMethod.class, publicAccess = true), // external types @GeneratePrism(value = XmlElementDecl.class, publicAccess = true) diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index e4d878ce4..4cde54e30 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -33,6 +33,7 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; +import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import org.mapstruct.ap.model.BeanMappingMethod; @@ -53,8 +54,10 @@ import org.mapstruct.ap.model.source.SourceMethod; import org.mapstruct.ap.option.Options; import org.mapstruct.ap.prism.DecoratedWithPrism; import org.mapstruct.ap.prism.MapperPrism; +import org.mapstruct.ap.prism.ReverseMappingMethodPrism; import org.mapstruct.ap.processor.creation.MappingResolverImpl; import org.mapstruct.ap.util.MapperConfig; +import org.mapstruct.ap.util.Strings; /** * A {@link ModelElementProcessor} which creates a {@link Mapper} from the given @@ -308,7 +311,7 @@ public class MapperCreationProcessor implements ModelElementProcessor rawMethods, SourceMethod method) { - for ( SourceMethod oneMethod : rawMethods ) { - if ( oneMethod.reverses( method ) ) { - return oneMethod; - } + private void mergeWithReverseMappings( SourceMethod reverseMappingMethod, SourceMethod method ) { + Map> newMappings = new HashMap>(); + if ( reverseMappingMethod != null && !reverseMappingMethod.getMappings().isEmpty() ) { + // define all the base mappings based on its forward counterpart + newMappings.putAll( reverse( reverseMappingMethod.getMappings() ) ); } - return null; + + if ( method.getMappings().isEmpty() ) { + // the mapping method is configuredByReverseMappingMethod, see SourceMethod#setMappings() + method.setMappings( newMappings ); + } + else { + // now add all of its own mappings + newMappings.putAll( method.getMappings() ); + method.getMappings().clear(); + // the mapping method is NOT configuredByReverseMappingMethod, + method.getMappings().putAll( newMappings ); + } + } + + + private SourceMethod getReverseMappingMethod(List rawMethods, SourceMethod method) { + + SourceMethod result = null; + + ReverseMappingMethodPrism reversePrism = ReverseMappingMethodPrism.getInstanceOn( method.getExecutable() ); + if ( reversePrism != null ) { + + // method is configured as being reverse method, collect candidates + List candidates = new ArrayList(); + for ( SourceMethod oneMethod : rawMethods ) { + if ( oneMethod.reverses( method ) ) { + candidates.add( oneMethod ); + } + } + + String configuredBy = reversePrism.configuredBy(); + if ( candidates.size() == 1 ) { + // no ambiguity: if no configuredBy is specified, or configuredBy specified and match + if ( configuredBy.isEmpty() ) { + result = candidates.get( 0 ); + } + else if ( candidates.get( 0 ).getName().equals( configuredBy ) ) { + result = candidates.get( 0 ); + } + else { + reportErrorWhenNonMatchingConfiguredBy( candidates.get( 0 ), method, reversePrism ); + } + } + else if ( candidates.size() > 1 ) { + // ambiguity: find a matching method that matches configuredBy + + List nameFilteredcandidates = new ArrayList(); + for ( SourceMethod candidate : candidates ) { + if ( candidate.getName().equals( configuredBy ) ) { + nameFilteredcandidates.add( candidate ); + } + } + + if ( nameFilteredcandidates.size() == 1 ) { + result = nameFilteredcandidates.get( 0 ); + } + else if ( nameFilteredcandidates.size() > 1 ) { + reportErrorWhenMoreConfiguredByMatch( nameFilteredcandidates, method, reversePrism ); + } + + if ( result == null ) { + reportErrorWhenAmbigousReverseMapping( candidates, method, reversePrism ); + } + } + + if ( result != null ) { + reportErrorIfForwardMethodHasReverseMappingMethodAnnotation( result, method, reversePrism ); + } + + } + return result; + } + + private void reportErrorIfForwardMethodHasReverseMappingMethodAnnotation( SourceMethod candidate, + SourceMethod method, ReverseMappingMethodPrism reversePrism ) { + + ReverseMappingMethodPrism candidatePrism = ReverseMappingMethodPrism.getInstanceOn( candidate.getExecutable() ); + if ( candidatePrism != null ) { + messager.printMessage( Diagnostic.Kind.ERROR, + String.format( "Resolved reverse mapping: \"%s\" should not carry the @ReverseMappingMethod " + + "annotation itself.", + candidate.getName() + ), + method.getExecutable(), + reversePrism.mirror ); + } + } + + private void reportErrorWhenAmbigousReverseMapping( List candidates, SourceMethod method, + ReverseMappingMethodPrism reversePrism ) { + + List candidateNames = new ArrayList(); + for (SourceMethod candidate : candidates ) { + candidateNames.add( candidate.getName() ); + } + + String configuredBy = reversePrism.configuredBy(); + if ( configuredBy.isEmpty() ) { + messager.printMessage( Diagnostic.Kind.ERROR, + String.format( "None of the candidates \"%s\" matches. Consider specifiying 'configuredBy'.", + Strings.join( candidateNames, "," ) + ), + method.getExecutable(), + reversePrism.mirror ); + } + else { + messager.printMessage( Diagnostic.Kind.ERROR, + String.format( "None of the candidates \"%s\", matches configuredBy: \"blah\".", + Strings.join( candidateNames, "," ), configuredBy + ), + method.getExecutable(), + reversePrism.mirror ); + } + } + + private void reportErrorWhenMoreConfiguredByMatch(List candidates, SourceMethod method, + ReverseMappingMethodPrism reversePrism ) { + + messager.printMessage( Diagnostic.Kind.ERROR, + String.format( "ConfiguredBy: \"%s\" matches more candidates: \"%s\".", + Strings.join( candidates, "," ), reversePrism.configuredBy() + ), + method.getExecutable(), + reversePrism.mirror ); + } + + private void reportErrorWhenNonMatchingConfiguredBy(SourceMethod onlyCandidate, SourceMethod method, + ReverseMappingMethodPrism reversePrism ) { + + messager.printMessage( Diagnostic.Kind.ERROR, + String.format( "ConfiguredBy: \"%s\" does not match the only candidate. Did you mean: \"%s\".", + reversePrism.configuredBy(), onlyCandidate.getName() + ), + method.getExecutable(), + reversePrism.mirror ); } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/CollectionMappingTest.java b/processor/src/test/java/org/mapstruct/ap/test/collection/CollectionMappingTest.java index 3bf96b2f5..64c335125 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/collection/CollectionMappingTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/CollectionMappingTest.java @@ -131,7 +131,7 @@ public class CollectionMappingTest { source.setOtherStringList( Arrays.asList( "Bob" ) ); List originalInstance = target.getOtherStringList(); - SourceTargetMapper.INSTANCE.sourceToTarget( source, target ); + SourceTargetMapper.INSTANCE.sourceToTargetTwoArg( source, target ); assertThat( target.getOtherStringList() ).isSameAs( originalInstance ); assertThat( target.getOtherStringList() ).containsExactly( "Bob" ); @@ -359,7 +359,7 @@ public class CollectionMappingTest { TestMap.setPuttAllCalled( false ); target.setOtherStringLongMap( originalInstance ); - SourceTargetMapper.INSTANCE.sourceToTarget( source, target ); + SourceTargetMapper.INSTANCE.sourceToTargetTwoArg( source, target ); assertThat( target.getOtherStringLongMap() ).isSameAs( originalInstance ); assertThat( target.getOtherStringLongMap() ).hasSize( 1 ); diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/SourceTargetMapper.java index 96f150a0c..bdd1306d8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/collection/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/SourceTargetMapper.java @@ -24,6 +24,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -38,17 +39,23 @@ public interface SourceTargetMapper { @Mapping(source = "stringList2", target = "stringListNoSetter") }) Target sourceToTarget(Source source); - + @ReverseMappingMethod(configuredBy = "sourceToTarget") Source targetToSource(Target target); - Target sourceToTarget(Source source, @MappingTarget Target target); + @Mappings({ + @Mapping(source = "integerList", target = "integerCollection"), + @Mapping(source = "integerSet", target = "set"), + @Mapping(source = "anotherIntegerSet", target = "anotherStringSet"), + @Mapping(source = "stringList2", target = "stringListNoSetter") + }) + Target sourceToTargetTwoArg(Source source, @MappingTarget Target target); Set integerSetToStringSet(Set integers); - + @ReverseMappingMethod Set stringSetToIntegerSet(Set strings); Set colourSetToStringSet(Set colours); - + @ReverseMappingMethod Set stringSetToColourSet(Set colours); Set integerSetToNumberSet(Set integers); diff --git a/processor/src/test/java/org/mapstruct/ap/test/collection/map/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/collection/map/SourceTargetMapper.java index 0d3858cd8..4811d8d07 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/collection/map/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/collection/map/SourceTargetMapper.java @@ -24,6 +24,7 @@ import java.util.Map; import org.mapstruct.MapMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingTarget; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper(uses = CustomNumberMapper.class) @@ -33,7 +34,7 @@ public interface SourceTargetMapper { @MapMapping(valueDateFormat = "dd.MM.yyyy") Map longDateMapToStringStringMap(Map source); - + @ReverseMappingMethod Map stringStringMapToLongDateMap(Map source); @MapMapping(valueDateFormat = "dd.MM.yyyy") @@ -45,7 +46,7 @@ public interface SourceTargetMapper { @MappingTarget Map target); Target sourceToTarget(Source source); - + @ReverseMappingMethod Source targetToSource(Target target); Map intIntToNumberNumberMap(Map source); diff --git a/processor/src/test/java/org/mapstruct/ap/test/complex/CarMapper.java b/processor/src/test/java/org/mapstruct/ap/test/complex/CarMapper.java index 10c4717ee..d076407fd 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/complex/CarMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/complex/CarMapper.java @@ -23,6 +23,7 @@ import java.util.List; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.ap.test.complex.other.DateMapper; import org.mapstruct.ap.test.complex.source.Car; import org.mapstruct.ap.test.complex.source.Person; @@ -40,18 +41,18 @@ public interface CarMapper { @Mapping(source = "manufacturingDate", target = "manufacturingYear") }) CarDto carToCarDto(Car car); - + @ReverseMappingMethod Car carDtoToCar(CarDto carDto); List carsToCarDtos(List cars); - + @ReverseMappingMethod List carDtosToCars(List carDtos); PersonDto personToPersonDto(Person person); - + @ReverseMappingMethod Person personDtoToPerson(PersonDto personDto); List personsToPersonDtos(List persons); - + @ReverseMappingMethod List personDtosToPersons(List personDtos); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/SourceTargetMapper.java index 3cc28c24c..b7683b2bb 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/SourceTargetMapper.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.conversion; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -33,6 +34,6 @@ public interface SourceTargetMapper { @Mapping(source = "baz", target = "qax") }) Target sourceToTarget(Source source); - + @ReverseMappingMethod Source targetToSource(Target target); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/date/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/date/SourceTargetMapper.java index 92bfaf8d1..fd65fa48a 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/date/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/date/SourceTargetMapper.java @@ -24,6 +24,7 @@ import java.util.List; import org.mapstruct.IterableMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -33,11 +34,11 @@ public interface SourceTargetMapper { @Mapping(source = "date", dateFormat = "dd.MM.yyyy") Target sourceToTarget(Source source); - + @ReverseMappingMethod Source targetToSource(Target target); @IterableMapping(dateFormat = "dd.MM.yyyy") List stringListToDateList(List dates); - + @ReverseMappingMethod List dateListToStringList(List strings); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/SourceTargetMapper.java index 3eece306a..8fcccf99d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/java8time/SourceTargetMapper.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.conversion.java8time; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; /** @@ -44,6 +45,10 @@ public interface SourceTargetMapper { @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } ) Target sourceToTarget(Source source); + @Mappings( { @Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ), + @Mapping( source = "localDateTime", dateFormat = LOCAL_DATE_TIME_FORMAT ), + @Mapping( source = "localDate", dateFormat = LOCAL_DATE_FORMAT ), + @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) } ) Target sourceToTargetDefaultMapping(Source source); @Mapping( source = "zonedDateTime", dateFormat = DATE_TIME_FORMAT ) @@ -76,5 +81,6 @@ public interface SourceTargetMapper { @Mapping( source = "localTime", dateFormat = LOCAL_TIME_FORMAT ) Source targetToSourceLocalTimeMapped(Target target); + @ReverseMappingMethod(configuredBy = "sourceToTarget") Source targetToSourceDefaultMapping(Target target); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java index 04006ccf8..eb22dff9d 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/JodaConversionTest.java @@ -196,7 +196,7 @@ public class JodaConversionTest { src.setDateTimeForCalendarConversion( dateTimeWithCalendar ); Target target = SourceTargetMapper.INSTANCE.sourceToTarget( src ); assertThat( target ).isNotNull(); - assertThat( target.getDateTimeForCalendarConversion() ).isEqualTo( calendar ); + assertThat( target.getDateTimeForCalendarConversion().getTime() ).isEqualTo( calendar.getTime() ); Source mappedSource = SourceTargetMapper.INSTANCE.targetToSource( target ); assertThat( mappedSource ).isNotNull(); diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java index 446c75899..591b62f45 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/jodatime/SourceTargetMapper.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.conversion.jodatime; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -44,6 +45,7 @@ public interface SourceTargetMapper { }) Target sourceToTarget(Source source); + @ReverseMappingMethod(configuredBy = "targetToSource") // TODO: FIXME Target sourceToTargetDefaultMapping(Source source); @Mapping(source = "dateTime", dateFormat = DATE_TIME_FORMAT) @@ -79,5 +81,6 @@ public interface SourceTargetMapper { @Mapping(source = "localTime", dateFormat = LOCAL_TIME_FORMAT) Source targetToSourceLocalTimeMapped(Target target); + @ReverseMappingMethod(configuredBy = "sourceToTarget") // TODO: FIXME Source targetToSourceDefaultMapping(Target target); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/ignore/AnimalMapper.java b/processor/src/test/java/org/mapstruct/ap/test/ignore/AnimalMapper.java index 4a2bfe2f1..40550b2ef 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/ignore/AnimalMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/ignore/AnimalMapper.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.ignore; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; import org.mapstruct.factory.Mappers; @Mapper @@ -33,6 +34,6 @@ public interface AnimalMapper { @Mapping(target = "age", ignore = true) }) AnimalDto animalToDto(Animal animal); - + @ReverseMappingMethod Animal animalDtoToAnimal(AnimalDto animalDto); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/ReverseMappingMethodTest.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/ReverseMappingMethodTest.java new file mode 100644 index 000000000..8307f5eb5 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/ReverseMappingMethodTest.java @@ -0,0 +1,157 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import javax.tools.Diagnostic.Kind; +import static org.fest.assertions.Assertions.assertThat; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; +import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic; +import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; + +/** + * @author Sjaak Derksen + * + */ +@IssueKey( "252" ) +@WithClasses( { Source.class, Target.class } ) +@RunWith( AnnotationProcessorTestRunner.class ) +public class ReverseMappingMethodTest { + + @Test + @WithClasses( { SourceTargetMapper.class } ) + public void shouldReverseMappingMethodMultipleCandidates() { + + Source source = new Source(); + source.setPropertyToIgnoreDownstream( "propToIgnoreDownStream" ); + source.setStringPropX( "1" ); + source.setIntegerPropX( 2 ); + + Target target = SourceTargetMapper.INSTANCE.forward( source ); + assertThat( target ).isNotNull(); + assertThat( target.getStringPropY() ).isEqualTo( "1" ); + assertThat( target.getIntegerPropY() ).isEqualTo( 2 ); + assertThat( target.getPropertyNotToIgnoreUpstream() ).isEqualTo( "propToIgnoreDownStream" ); + + source = SourceTargetMapper.INSTANCE.reverse( target ); + assertThat( source ).isNotNull(); + assertThat( source.getStringPropX() ).isEqualTo( "1" ); + assertThat( source.getIntegerPropX() ).isEqualTo( 2 ); + assertThat( source.getSomeConstantDownstream() ).isEqualTo( "test" ); + assertThat( source.getPropertyToIgnoreDownstream() ).isNull(); + + } + + @Test + @WithClasses( { SourceTargetMapperAmbigious1.class } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = SourceTargetMapperAmbigious1.class, + kind = Kind.ERROR, + line = 51, + messageRegExp = "None of the candidates \"forward,forwardNotToReverse\" matches. " + + "Consider specifiying 'configuredBy'." ), + @Diagnostic( type = SourceTargetMapperAmbigious1.class, + kind = Kind.WARNING, + line = 56, + messageRegExp = "Unmapped target properties: \"stringPropX, integerPropX\"" ) + } + ) + public void shouldRaiseAmbigousReverseMethodError() { + } + + @Test + @WithClasses( { SourceTargetMapperAmbigious2.class } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = SourceTargetMapperAmbigious2.class, + kind = Kind.ERROR, + line = 51, + messageRegExp = "None of the candidates \"forward,forwardNotToReverse\", matches configuredBy: " + + "\"blah\"." ), + @Diagnostic( type = SourceTargetMapperAmbigious2.class, + kind = Kind.WARNING, + line = 56, + messageRegExp = "Unmapped target properties: \"stringPropX, integerPropX\"" ) + } + ) + public void shouldRaiseAmbigousReverseMethodErrorWrongName() { + } + + @Test + @WithClasses( { SourceTargetMapperAmbigious3.class } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = SourceTargetMapperAmbigious3.class, + kind = Kind.ERROR, + line = 52, + messageRegExp = "ConfiguredBy:.*forward.*forward.*@MappingTarget.*matches more candidates:" + + " \"forward\"." ), + @Diagnostic( type = SourceTargetMapperAmbigious3.class, + kind = Kind.WARNING, + line = 57, + messageRegExp = "Unmapped target properties: \"stringPropX, integerPropX\"" ) + } + ) + public void shouldRaiseAmbigousReverseMethodErrorDuplicatedName() { + } + + + @Test + @WithClasses( { SourceTargetMapperErroneouslyAnnotated.class } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = SourceTargetMapperErroneouslyAnnotated.class, + kind = Kind.ERROR, + line = 51, + messageRegExp = "Resolved reverse mapping: \"reverse\" should not carry the " + + "@ReverseMappingMethod annotation itself." ) + } + ) + public void shouldUseWronglyAnnotatedError() { + } + + @Test + @WithClasses( { SourceTargetMapperNonMatchingName.class } ) + @ExpectedCompilationOutcome( + value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic( type = SourceTargetMapperNonMatchingName.class, + kind = Kind.ERROR, + line = 44, + messageRegExp = "ConfiguredBy: \"blah\" does not match the only candidate. Did you mean: " + + "\"forward\"." ), + @Diagnostic( type = SourceTargetMapperNonMatchingName.class, + kind = Kind.WARNING, + line = 49, + messageRegExp = "Unmapped target properties: \"stringPropX, integerPropX\"" ) + } + ) + public void shouldAdviceOnSpecifyingCorrectName() { + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/Source.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/Source.java new file mode 100644 index 000000000..c1758cb17 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/Source.java @@ -0,0 +1,68 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +/** + * + * @author Sjaak Derksen + */ +public class Source { + + private String stringPropX; + + private Integer integerPropX; + + private String someConstantDownstream; + + private String propertyToIgnoreDownstream; + + public String getStringPropX() { + return stringPropX; + } + + public void setStringPropX( String stringPropX ) { + this.stringPropX = stringPropX; + } + + public Integer getIntegerPropX() { + return integerPropX; + } + + public void setIntegerPropX( Integer integerPropX ) { + this.integerPropX = integerPropX; + } + + public String getSomeConstantDownstream() { + return someConstantDownstream; + } + + public void setSomeConstantDownstream( String someConstantDownstream ) { + this.someConstantDownstream = someConstantDownstream; + } + + public String getPropertyToIgnoreDownstream() { + return propertyToIgnoreDownstream; + } + + public void setPropertyToIgnoreDownstream( String propertyToIgnoreDownstream ) { + this.propertyToIgnoreDownstream = propertyToIgnoreDownstream; + } + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapper.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapper.java new file mode 100644 index 000000000..aa1e1c390 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapper.java @@ -0,0 +1,57 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapper { + + SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forwardNotToReverse( Source source ); + + @ReverseMappingMethod(configuredBy = "forward") + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious1.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious1.java new file mode 100644 index 000000000..8365ec116 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious1.java @@ -0,0 +1,57 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapperAmbigious1 { + + SourceTargetMapperAmbigious1 INSTANCE = Mappers.getMapper( SourceTargetMapperAmbigious1.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forwardNotToReverse( Source source ); + + @ReverseMappingMethod + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious2.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious2.java new file mode 100644 index 000000000..dc297f23c --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious2.java @@ -0,0 +1,57 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapperAmbigious2 { + + SourceTargetMapperAmbigious2 INSTANCE = Mappers.getMapper( SourceTargetMapperAmbigious2.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forwardNotToReverse( Source source ); + + @ReverseMappingMethod(configuredBy = "blah") + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious3.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious3.java new file mode 100644 index 000000000..4643603f1 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperAmbigious3.java @@ -0,0 +1,58 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapperAmbigious3 { + + SourceTargetMapperAmbigious3 INSTANCE = Mappers.getMapper( SourceTargetMapperAmbigious3.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source, @MappingTarget Target target ); + + @ReverseMappingMethod(configuredBy = "forward") + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperErroneouslyAnnotated.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperErroneouslyAnnotated.java new file mode 100644 index 000000000..b86f3cac8 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperErroneouslyAnnotated.java @@ -0,0 +1,58 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapperErroneouslyAnnotated { + + SourceTargetMapperErroneouslyAnnotated INSTANCE = Mappers.getMapper( SourceTargetMapperErroneouslyAnnotated.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @ReverseMappingMethod(configuredBy = "forward") + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); + + @ReverseMappingMethod(configuredBy = "reverse") + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward2( Source source ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperNonMatchingName.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperNonMatchingName.java new file mode 100644 index 000000000..88ccb7aa4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/SourceTargetMapperNonMatchingName.java @@ -0,0 +1,50 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.ReverseMappingMethod; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ + +@Mapper +public interface SourceTargetMapperNonMatchingName { + + SourceTargetMapperNonMatchingName INSTANCE = Mappers.getMapper( SourceTargetMapperNonMatchingName.class ); + + @Mappings( { + @Mapping( source = "stringPropX", target = "stringPropY" ), + @Mapping( source = "integerPropX", target = "integerPropY" ), + @Mapping( source = "propertyToIgnoreDownstream", target = "propertyNotToIgnoreUpstream" ) + } ) + Target forward( Source source ); + + @ReverseMappingMethod(configuredBy = "blah") + @Mappings( { + @Mapping( target = "someConstantDownstream", constant = "test" ), + @Mapping( source = "propertyToIgnoreDownstream", ignore = true ) + } ) + Source reverse( Target target ); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/reverse/Target.java b/processor/src/test/java/org/mapstruct/ap/test/reverse/Target.java new file mode 100644 index 000000000..8cd72aefa --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/reverse/Target.java @@ -0,0 +1,58 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.reverse; + +/** + * + * @author Sjaak Derksen + */ +public class Target { + + private String stringPropY; + + private Integer integerPropY; + + private String propertyNotToIgnoreUpstream; + + public String getStringPropY() { + return stringPropY; + } + + public void setStringPropY( String stringPropY ) { + this.stringPropY = stringPropY; + } + + public Integer getIntegerPropY() { + return integerPropY; + } + + public void setIntegerPropY( Integer integerPropY ) { + this.integerPropY = integerPropY; + } + + public String getPropertyNotToIgnoreUpstream() { + return propertyNotToIgnoreUpstream; + } + + public void setPropertyNotToIgnoreUpstream( String propertyNotToIgnoreUpstream ) { + this.propertyNotToIgnoreUpstream = propertyNotToIgnoreUpstream; + } + + +}