#1 Providing infrastructure for implicit conversions

This commit is contained in:
Gunnar Morling 2013-03-02 15:10:48 +01:00
parent df6ae29f2d
commit 192cfc8937
16 changed files with 611 additions and 9 deletions

View File

@ -41,6 +41,8 @@ import javax.lang.model.util.SimpleAnnotationValueVisitor6;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import org.mapstruct.ap.conversion.Conversion;
import org.mapstruct.ap.conversion.Conversions;
import org.mapstruct.ap.model.BeanMapping; import org.mapstruct.ap.model.BeanMapping;
import org.mapstruct.ap.model.Mapper; import org.mapstruct.ap.model.Mapper;
import org.mapstruct.ap.model.MappingMethod; import org.mapstruct.ap.model.MappingMethod;
@ -52,7 +54,6 @@ import org.mapstruct.ap.model.source.Method;
import org.mapstruct.ap.model.source.Parameter; import org.mapstruct.ap.model.source.Parameter;
import org.mapstruct.ap.writer.ModelWriter; import org.mapstruct.ap.writer.ModelWriter;
import static javax.lang.model.util.ElementFilter.methodsIn; import static javax.lang.model.util.ElementFilter.methodsIn;
public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> { public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
@ -131,10 +132,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
Method propertyMappingMethod = getPropertyMappingMethod( methods, property ); Method propertyMappingMethod = getPropertyMappingMethod( methods, property );
Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property ); Method reversePropertyMappingMethod = getReversePropertyMappingMethod( methods, property );
Conversion conversion = Conversions.getConversion( property.getSourceType(), property.getTargetType() );
propertyMappings.add( propertyMappings.add(
new PropertyMapping( new PropertyMapping(
property.getSourceName(), property.getSourceName(),
property.getSourceType(),
property.getTargetName(), property.getTargetName(),
property.getTargetType(),
property.getConverterType(), property.getConverterType(),
propertyMappingMethod != null ? new MappingMethod( propertyMappingMethod != null ? new MappingMethod(
propertyMappingMethod.getName(), propertyMappingMethod.getName(),
@ -143,6 +148,16 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
reversePropertyMappingMethod != null ? new MappingMethod( reversePropertyMappingMethod != null ? new MappingMethod(
reversePropertyMappingMethod.getName(), reversePropertyMappingMethod.getName(),
reversePropertyMappingMethod.getParameterName() reversePropertyMappingMethod.getParameterName()
) : null,
conversion != null ? conversion.to(
mappingMethod.getParameterName() + "." + getAccessor(
property.getSourceName()
)
) : null,
conversion != null ? conversion.from(
reverseMappingMethod.getParameterName() + "." + getAccessor(
property.getTargetName()
)
) : null ) : null
) )
); );
@ -168,6 +183,14 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
return mapper; return mapper;
} }
private String getAccessor(String name) {
return "get" + capitalize( name ) + "()";
}
private String capitalize(String name) {
return name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
}
private MappingMethod getElementMappingMethod(Iterable<Method> methods, Method method) { private MappingMethod getElementMappingMethod(Iterable<Method> methods, Method method) {
Method elementMappingMethod = null; Method elementMappingMethod = null;
for ( Method oneMethod : methods ) { for ( Method oneMethod : methods ) {

View File

@ -0,0 +1,23 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public interface Conversion {
String to(String sourcePropertyAccessor);
String from(String targetPropertyAccessor);
}

View File

@ -0,0 +1,98 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.mapstruct.ap.model.Type;
import static org.mapstruct.ap.conversion.ReverseConversion.reverse;
public class Conversions {
private static ConcurrentMap<Key, Conversion> conversions = new ConcurrentHashMap<Conversions.Key, Conversion>();
static {
register( int.class, Long.class, new IntLongConversion() );
register( int.class, String.class, new IntStringConversion() );
}
private static void register(Class<?> sourceType, Class<?> targetType, Conversion conversion) {
conversions.put( Key.forClasses( sourceType, targetType ), conversion );
conversions.put( Key.forClasses( targetType, sourceType ), reverse( conversion ) );
}
public static Conversion getConversion(Type sourceType, Type targetType) {
return conversions.get( new Key( sourceType, targetType ) );
}
private static class Key {
private final Type sourceType;
private final Type targetType;
private static Key forClasses(Class<?> sourceType, Class<?> targetType) {
return new Key( Type.forClass( sourceType ), Type.forClass( targetType ) );
}
private Key(Type sourceType, Type targetType) {
this.sourceType = sourceType;
this.targetType = targetType;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ( ( sourceType == null ) ? 0 : sourceType.hashCode() );
result = prime * result
+ ( ( targetType == null ) ? 0 : targetType.hashCode() );
return result;
}
@Override
public boolean equals(Object obj) {
if ( this == obj ) {
return true;
}
if ( obj == null ) {
return false;
}
if ( getClass() != obj.getClass() ) {
return false;
}
Key other = (Key) obj;
if ( sourceType == null ) {
if ( other.sourceType != null ) {
return false;
}
}
else if ( !sourceType.equals( other.sourceType ) ) {
return false;
}
if ( targetType == null ) {
if ( other.targetType != null ) {
return false;
}
}
else if ( !targetType.equals( other.targetType ) ) {
return false;
}
return true;
}
}
}

View File

@ -0,0 +1,29 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public class IntLongConversion implements Conversion {
@Override
public String to(String sourcePropertyAccessor) {
return "Long.valueOf( " + sourcePropertyAccessor + " )";
}
@Override
public String from(String targetPropertyAccessor) {
return targetPropertyAccessor + ".intValue()";
}
}

View File

@ -0,0 +1,29 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public class IntStringConversion implements Conversion {
@Override
public String to(String sourcePropertyAccessor) {
return "String.valueOf( " + sourcePropertyAccessor + " )";
}
@Override
public String from(String targetPropertyAccessor) {
return "Integer.parseInt( " + targetPropertyAccessor + " )";
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public class ReverseConversion implements Conversion {
private Conversion conversion;
public static ReverseConversion reverse(Conversion conversion) {
return new ReverseConversion( conversion );
}
private ReverseConversion(Conversion conversion) {
this.conversion = conversion;
}
@Override
public String to(String sourcePropertyAccessor) {
return conversion.from( sourcePropertyAccessor );
}
@Override
public String from(String targetPropertyAccessor) {
return conversion.to( targetPropertyAccessor );
}
}

View File

@ -18,27 +18,43 @@ package org.mapstruct.ap.model;
public class PropertyMapping { public class PropertyMapping {
private final String sourceName; private final String sourceName;
private final Type sourceType;
private final String targetName; private final String targetName;
private final Type targetType;
private final Type converterType; private final Type converterType;
private final MappingMethod mappingMethod; private final MappingMethod mappingMethod;
private final MappingMethod reverseMappingMethod; private final MappingMethod reverseMappingMethod;
private final String toConversion;
private final String fromConversion;
public PropertyMapping(String sourceName, String targetName, Type converterType, MappingMethod mappingMethod, MappingMethod reverseMappingMethod) { public PropertyMapping(String sourceName, Type sourceType, String targetName, Type targetType, Type converterType, MappingMethod mappingMethod, MappingMethod reverseMappingMethod, String toConversion, String fromConversion) {
this.sourceName = sourceName; this.sourceName = sourceName;
this.sourceType = sourceType;
this.targetName = targetName; this.targetName = targetName;
this.targetType = targetType;
this.converterType = converterType; this.converterType = converterType;
this.mappingMethod = mappingMethod; this.mappingMethod = mappingMethod;
this.reverseMappingMethod = reverseMappingMethod; this.reverseMappingMethod = reverseMappingMethod;
this.toConversion = toConversion;
this.fromConversion = fromConversion;
} }
public String getSourceName() { public String getSourceName() {
return sourceName; return sourceName;
} }
public Type getSourceType() {
return sourceType;
}
public String getTargetName() { public String getTargetName() {
return targetName; return targetName;
} }
public Type getTargetType() {
return targetType;
}
public Type getConverterType() { public Type getConverterType() {
return converterType; return converterType;
} }
@ -50,4 +66,12 @@ public class PropertyMapping {
public MappingMethod getReverseMappingMethod() { public MappingMethod getReverseMappingMethod() {
return reverseMappingMethod; return reverseMappingMethod;
} }
public String getToConversion() {
return toConversion;
}
public String getFromConversion() {
return fromConversion;
}
} }

View File

@ -15,6 +15,10 @@
*/ */
package org.mapstruct.ap.model; package org.mapstruct.ap.model;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/** /**
* Represents the type of a bean property, parameter etc. * Represents the type of a bean property, parameter etc.
* *
@ -22,10 +26,26 @@ package org.mapstruct.ap.model;
*/ */
public class Type { public class Type {
private final static Set<String> primitiveTypeNames = new HashSet<String>(
Arrays.asList( "boolean", "char", "byte", "short", "int", "long", "float", "double" )
);
private final String packageName; private final String packageName;
private final String name; private final String name;
private final Type elementType; private final Type elementType;
public static Type forClass(Class<?> clazz) {
Package pakkage = clazz.getPackage();
if ( pakkage != null ) {
return new Type( pakkage.getName(), clazz.getSimpleName() );
}
else {
return new Type( clazz.getSimpleName() );
}
}
public Type(String name) { public Type(String name) {
this.packageName = null; this.packageName = null;
this.name = name; this.name = name;
@ -56,6 +76,10 @@ public class Type {
return elementType; return elementType;
} }
public boolean isPrimitive() {
return packageName == null && primitiveTypeNames.contains( name );
}
@Override @Override
public String toString() { public String toString() {
if ( packageName == null ) { if ( packageName == null ) {

View File

@ -26,7 +26,6 @@ public class ${implementationName} implements ${interfaceName} {
<#if beanMapping.iterableMapping == true> <#if beanMapping.iterableMapping == true>
@Override @Override
public ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.mappingMethod.parameterName}) { public ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.mappingMethod.parameterName}) {
${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>(); ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}>();
for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) { for ( ${beanMapping.sourceType.elementType.name} ${beanMapping.sourceType.elementType.name?uncap_first} : ${beanMapping.mappingMethod.parameterName} ) {
@ -38,11 +37,18 @@ public class ${implementationName} implements ${interfaceName} {
<#else> <#else>
@Override @Override
public ${beanMapping.targetType.name} ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name} ${beanMapping.mappingMethod.parameterName}) { public ${beanMapping.targetType.name} ${beanMapping.mappingMethod.name}(${beanMapping.sourceType.name} ${beanMapping.mappingMethod.parameterName}) {
${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}(); ${beanMapping.targetType.name} ${beanMapping.targetType.name?uncap_first} = new ${beanMapping.targetType.name}();
<#list beanMapping.propertyMappings as propertyMapping> <#list beanMapping.propertyMappings as propertyMapping>
<#if propertyMapping.converterType??> <#if propertyMapping.toConversion??>
<#if propertyMapping.targetType.primitive == true>
if( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() != null ) {
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${propertyMapping.toConversion} );
}
<#else>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${propertyMapping.toConversion} );
</#if>
<#elseif propertyMapping.converterType??>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( new ${propertyMapping.converterType.name}().from( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) ); ${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( new ${propertyMapping.converterType.name}().from( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) );
<#elseif propertyMapping.mappingMethod??> <#elseif propertyMapping.mappingMethod??>
${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${propertyMapping.mappingMethod.name}( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) ); ${beanMapping.targetType.name?uncap_first}.set${propertyMapping.targetName?cap_first}( ${propertyMapping.mappingMethod.name}( ${beanMapping.mappingMethod.parameterName}.get${propertyMapping.sourceName?cap_first}() ) );
@ -56,11 +62,9 @@ public class ${implementationName} implements ${interfaceName} {
</#if> </#if>
<#if beanMapping.reverseMappingMethod??> <#if beanMapping.reverseMappingMethod??>
<#if beanMapping.iterableMapping == true> <#if beanMapping.iterableMapping == true>
@Override @Override
public ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.reverseMappingMethod.parameterName}) { public ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.reverseMappingMethod.name}(${beanMapping.targetType.name}<${beanMapping.targetType.elementType.name}> ${beanMapping.reverseMappingMethod.parameterName}) {
${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>(); ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}> ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}<${beanMapping.sourceType.elementType.name}>();
for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) { for ( ${beanMapping.targetType.elementType.name} ${beanMapping.targetType.elementType.name?uncap_first} : ${beanMapping.reverseMappingMethod.parameterName} ) {
@ -75,7 +79,15 @@ public class ${implementationName} implements ${interfaceName} {
${beanMapping.sourceType.name} ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}(); ${beanMapping.sourceType.name} ${beanMapping.sourceType.name?uncap_first} = new ${beanMapping.sourceType.name}();
<#list beanMapping.propertyMappings as propertyMapping> <#list beanMapping.propertyMappings as propertyMapping>
<#if propertyMapping.converterType??> <#if propertyMapping.fromConversion??>
<#if propertyMapping.sourceType.primitive == true>
if( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() != null ) {
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${propertyMapping.fromConversion} );
}
<#else>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${propertyMapping.fromConversion} );
</#if>
<#elseif propertyMapping.converterType??>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( new ${propertyMapping.converterType.name}().to( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) ); ${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( new ${propertyMapping.converterType.name}().to( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) );
<#elseif propertyMapping.reverseMappingMethod??> <#elseif propertyMapping.reverseMappingMethod??>
${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${propertyMapping.reverseMappingMethod.name}( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) ); ${beanMapping.sourceType.name?uncap_first}.set${propertyMapping.sourceName?cap_first}( ${propertyMapping.reverseMappingMethod.name}( ${beanMapping.reverseMappingMethod.parameterName}.get${propertyMapping.targetName?cap_first}() ) );

View File

@ -0,0 +1,119 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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;
import java.io.File;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import org.mapstruct.ap.test.conversion.Source;
import org.mapstruct.ap.test.conversion.SourceTargetMapper;
import org.mapstruct.ap.test.conversion.Target;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
public class ConversionTest extends MapperTestBase {
private DiagnosticCollector<JavaFileObject> diagnostics;
public ConversionTest() {
super( "mapstruct.jar" );
}
@BeforeMethod
public void generateMapperImplementation() {
diagnostics = new DiagnosticCollector<JavaFileObject>();
File[] sourceFiles = getSourceFiles(
Source.class,
Target.class,
SourceTargetMapper.class
);
boolean compilationSuccessful = compile( diagnostics, sourceFiles );
assertThat( compilationSuccessful ).describedAs( "Compilation failed: " + diagnostics.getDiagnostics() )
.isTrue();
}
@Test
public void shouldApplyConversions() {
Source source = new Source();
source.setFoo( 42 );
source.setBar( 23L );
source.setZip( 73 );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 42 ) );
assertThat( target.getBar() ).isEqualTo( 23 );
assertThat( target.getZip() ).isEqualTo( "73" );
}
@Test
public void shouldHandleNulls() {
Source source = new Source();
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( Long.valueOf( 0 ) );
assertThat( target.getBar() ).isEqualTo( 0 );
assertThat( target.getZip() ).isEqualTo( "0" );
}
@Test
public void shouldApplyConversionsToMappedProperties() {
Source source = new Source();
source.setQax( 42 );
source.setBaz( 23L );
Target target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getBaz() ).isEqualTo( Long.valueOf( 42 ) );
assertThat( target.getQax() ).isEqualTo( 23 );
}
@Test
public void shouldApplyConversionsForReverseMapping() {
Target target = new Target();
target.setFoo( 42L );
target.setBar( 23 );
target.setZip( "73" );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
assertThat( source ).isNotNull();
assertThat( source.getFoo() ).isEqualTo( 42 );
assertThat( source.getBar() ).isEqualTo( 23 );
assertThat( source.getZip() ).isEqualTo( 73 );
}
@Test
public void shouldApplyConversionsToMappedPropertiesForReverseMapping() {
Target target = new Target();
target.setQax( 42 );
target.setBaz( 23L );
Source source = SourceTargetMapper.INSTANCE.targetToSource( target );
assertThat( source ).isNotNull();
assertThat( source.getBaz() ).isEqualTo( 42 );
assertThat( source.getQax() ).isEqualTo( 23 );
}
}

View File

@ -0,0 +1,65 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public class Source {
private int foo;
private Long bar;
private int qax;
private Long baz;
private int zip;
public int getFoo() {
return foo;
}
public void setFoo(int foo) {
this.foo = foo;
}
public Long getBar() {
return bar;
}
public void setBar(Long bar) {
this.bar = bar;
}
public int getQax() {
return qax;
}
public void setQax(int qax) {
this.qax = qax;
}
public Long getBaz() {
return baz;
}
public void setBaz(Long baz) {
this.baz = baz;
}
public int getZip() {
return zip;
}
public void setZip(int zip) {
this.zip = zip;
}
}

View File

@ -0,0 +1,35 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
import org.mapstruct.Mapper;
import org.mapstruct.Mappers;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
@Mapper
public interface SourceTargetMapper {
public static SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
@Mappings({
@Mapping(source = "qax", target = "baz"),
@Mapping(source = "baz", target = "qax")
})
Target sourceToTarget(Source source);
Source targetToSource(Target target);
}

View File

@ -0,0 +1,65 @@
/**
* Copyright 2012-2013 Gunnar Morling (http://www.gunnarmorling.de/)
*
* 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.conversion;
public class Target {
private Long foo;
private int bar;
private Long baz;
private int qax;
private String zip;
public Long getFoo() {
return foo;
}
public void setFoo(Long foo) {
this.foo = foo;
}
public int getBar() {
return bar;
}
public void setBar(int bar) {
this.bar = bar;
}
public Long getBaz() {
return baz;
}
public void setBaz(Long baz) {
this.baz = baz;
}
public int getQax() {
return qax;
}
public void setQax(int qax) {
this.qax = qax;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
}

View File

@ -24,6 +24,7 @@ public class Car {
private int yearOfManufacture; private int yearOfManufacture;
private Person driver; private Person driver;
private ArrayList<Person> passengers; private ArrayList<Person> passengers;
private int price;
public Car() { public Car() {
} }
@ -75,4 +76,12 @@ public class Car {
public void setPassengers(ArrayList<Person> passengers) { public void setPassengers(ArrayList<Person> passengers) {
this.passengers = passengers; this.passengers = passengers;
} }
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
} }

View File

@ -24,6 +24,7 @@ public class CarDto {
private String manufacturingYear; private String manufacturingYear;
private PersonDto driver; private PersonDto driver;
private ArrayList<PersonDto> passengers; private ArrayList<PersonDto> passengers;
private Long price;
public CarDto() { public CarDto() {
} }
@ -75,4 +76,12 @@ public class CarDto {
public void setPassengers(ArrayList<PersonDto> passengers) { public void setPassengers(ArrayList<PersonDto> passengers) {
this.passengers = passengers; this.passengers = passengers;
} }
public Long getPrice() {
return price;
}
public void setPrice(Long price) {
this.price = price;
}
} }

View File

@ -22,7 +22,6 @@ import org.mapstruct.Mappers;
import org.mapstruct.Mapping; import org.mapstruct.Mapping;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
@Mapper @Mapper
public interface CarMapper { public interface CarMapper {