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:
+ *
+ * - the source parameter should match the return type (or the parameter indicated as {@link MappingTarget}
+ * - the target parameter should match the source parameter
+ *
+ *
+ * @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;
+ }
+
+
+}