#1102 Add support for Auto forging of Enum properties

This commit is contained in:
Filip Hrisafov 2017-03-12 15:34:46 +01:00 committed by Andreas Gudian
parent 12f1cc0777
commit d4c6250944
32 changed files with 1018 additions and 42 deletions

View File

@ -21,6 +21,7 @@ package org.mapstruct.ap.internal.model;
import org.mapstruct.ap.internal.model.assignment.Assignment; import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.ParameterBinding; import org.mapstruct.ap.internal.model.common.ParameterBinding;
import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.MappingMethodUtils;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
/** /**
@ -55,11 +56,21 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
* *
* @return See above * @return See above
*/ */
Assignment createForgedBeanAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod) { Assignment createForgedAssignment(SourceRHS sourceRHS, ForgedMethod forgedMethod) {
BeanMappingMethod forgedMappingMethod = new BeanMappingMethod.Builder() MappingMethod forgedMappingMethod;
.forgedMethod( forgedMethod ) if ( MappingMethodUtils.isEnumMapping( forgedMethod ) ) {
.mappingContext( ctx ) forgedMappingMethod = new ValueMappingMethod.Builder()
.build(); .method( forgedMethod )
.valueMappings( forgedMethod.getMappingOptions().getValueMappings() )
.mappingContext( ctx )
.build();
}
else {
forgedMappingMethod = new BeanMappingMethod.Builder()
.forgedMethod( forgedMethod )
.mappingContext( ctx )
.build();
}
return createForgedAssignment( sourceRHS, forgedMethod, forgedMappingMethod ); return createForgedAssignment( sourceRHS, forgedMethod, forgedMappingMethod );
} }

View File

@ -73,7 +73,7 @@ public abstract class AbstractMappingMethodBuilder<B extends AbstractMappingMeth
true true
); );
return createForgedBeanAssignment( sourceRHS, forgedMethod ); return createForgedAssignment( sourceRHS, forgedMethod );
} }
private String getName(Type sourceType, Type targetType) { private String getName(Type sourceType, Type targetType) {

View File

@ -634,7 +634,8 @@ public class PropertyMapping extends ModelElement {
// there's only one case for forging a method with mapping options: nested target properties. // there's only one case for forging a method with mapping options: nested target properties.
// They should forge an update method only if we set the forceUpdateMethod. This is set to true, // They should forge an update method only if we set the forceUpdateMethod. This is set to true,
// because we are forging a Mapping for a method with multiple source parameters. // because we are forging a Mapping for a method with multiple source parameters.
if ( method.isUpdateMethod() || forceUpdateMethod ) { // If the target type is enum, then we can't create an update method
if ( !targetType.isEnumType() && ( method.isUpdateMethod() || forceUpdateMethod ) ) {
parameters.add( Parameter.forForgedMappingTarget( targetType ) ); parameters.add( Parameter.forForgedMappingTarget( targetType ) );
returnType = ctx.getTypeFactory().createVoidType(); returnType = ctx.getTypeFactory().createVoidType();
} }
@ -653,7 +654,7 @@ public class PropertyMapping extends ModelElement {
forgeMethodWithMappingOptions, forgeMethodWithMappingOptions,
forgedNamedBased forgedNamedBased
); );
return createForgedBeanAssignment( sourceRHS, forgedMethod ); return createForgedAssignment( sourceRHS, forgedMethod );
} }
private ForgedMethodHistory getForgedMethodHistory(SourceRHS sourceRHS) { private ForgedMethodHistory getForgedMethodHistory(SourceRHS sourceRHS) {

View File

@ -28,9 +28,10 @@ import java.util.Set;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import org.mapstruct.ap.internal.model.common.Parameter; import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.source.ForgedMethodHistory;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.model.source.ValueMapping; import org.mapstruct.ap.internal.model.source.ValueMapping;
import org.mapstruct.ap.internal.prism.BeanMappingPrism; import org.mapstruct.ap.internal.prism.BeanMappingPrism;
import org.mapstruct.ap.internal.prism.MappingConstantsPrism; import org.mapstruct.ap.internal.prism.MappingConstantsPrism;
@ -49,10 +50,11 @@ public class ValueMappingMethod extends MappingMethod {
private final String defaultTarget; private final String defaultTarget;
private final String nullTarget; private final String nullTarget;
private final boolean throwIllegalArgumentException; private final boolean throwIllegalArgumentException;
private final boolean overridden;
public static class Builder { public static class Builder {
private SourceMethod method; private Method method;
private MappingBuilderContext ctx; private MappingBuilderContext ctx;
private final List<ValueMapping> trueValueMappings = new ArrayList<ValueMapping>(); private final List<ValueMapping> trueValueMappings = new ArrayList<ValueMapping>();
private ValueMapping defaultTargetValue = null; private ValueMapping defaultTargetValue = null;
@ -64,7 +66,7 @@ public class ValueMappingMethod extends MappingMethod {
return this; return this;
} }
public Builder souceMethod(SourceMethod sourceMethod) { public Builder method(Method sourceMethod) {
this.method = sourceMethod; this.method = sourceMethod;
return this; return this;
} }
@ -128,7 +130,7 @@ public class ValueMappingMethod extends MappingMethod {
throwIllegalArgumentException, beforeMappingMethods, afterMappingMethods ); throwIllegalArgumentException, beforeMappingMethods, afterMappingMethods );
} }
private List<MappingEntry> enumToEnumMapping(SourceMethod method) { private List<MappingEntry> enumToEnumMapping(Method method) {
List<MappingEntry> mappings = new ArrayList<MappingEntry>(); List<MappingEntry> mappings = new ArrayList<MappingEntry>();
List<String> unmappedSourceConstants List<String> unmappedSourceConstants
@ -161,10 +163,20 @@ public class ValueMappingMethod extends MappingMethod {
} }
if ( defaultTargetValue == null && !unmappedSourceConstants.isEmpty() ) { if ( defaultTargetValue == null && !unmappedSourceConstants.isEmpty() ) {
String sourceErrorMessage = "source";
String targetErrorMessage = "target";
if ( method instanceof ForgedMethod && ( (ForgedMethod) method ).getHistory() != null ) {
ForgedMethodHistory history = ( (ForgedMethod) method ).getHistory();
sourceErrorMessage = history.createSourcePropertyErrorMessage();
targetErrorMessage =
"\"" + history.getTargetType().toString() + " " + history.createTargetPropertyName() + "\"";
}
// all sources should now be matched, there's no default to fall back to, so if sources remain, // all sources should now be matched, there's no default to fall back to, so if sources remain,
// we have an issue. // we have an issue.
ctx.getMessager().printMessage( method.getExecutable(), ctx.getMessager().printMessage( method.getExecutable(),
Message.VALUE_MAPPING_UNMAPPED_SOURCES, Message.VALUE_MAPPING_UNMAPPED_SOURCES,
sourceErrorMessage,
targetErrorMessage,
Strings.join( unmappedSourceConstants, ", " ) Strings.join( unmappedSourceConstants, ", " )
); );
@ -173,7 +185,7 @@ public class ValueMappingMethod extends MappingMethod {
return mappings; return mappings;
} }
private SelectionParameters getSelectionParameters(SourceMethod method) { private SelectionParameters getSelectionParameters(Method method) {
BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() ); BeanMappingPrism beanMappingPrism = BeanMappingPrism.getInstanceOn( method.getExecutable() );
if ( beanMappingPrism != null ) { if ( beanMappingPrism != null ) {
List<TypeMirror> qualifiers = beanMappingPrism.qualifiedBy(); List<TypeMirror> qualifiers = beanMappingPrism.qualifiedBy();
@ -184,7 +196,7 @@ public class ValueMappingMethod extends MappingMethod {
return null; return null;
} }
private boolean reportErrorIfMappedEnumConstantsDontExist(SourceMethod method) { private boolean reportErrorIfMappedEnumConstantsDontExist(Method method) {
List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants(); List<String> sourceEnumConstants = first( method.getSourceParameters() ).getType().getEnumConstants();
List<String> targetEnumConstants = method.getReturnType().getEnumConstants(); List<String> targetEnumConstants = method.getReturnType().getEnumConstants();
@ -251,6 +263,7 @@ public class ValueMappingMethod extends MappingMethod {
this.nullTarget = nullTarget; this.nullTarget = nullTarget;
this.defaultTarget = defaultTarget; this.defaultTarget = defaultTarget;
this.throwIllegalArgumentException = throwIllegalArgumentException; this.throwIllegalArgumentException = throwIllegalArgumentException;
this.overridden = method.overridesMethod();
} }
public List<MappingEntry> getValueMappings() { public List<MappingEntry> getValueMappings() {
@ -273,6 +286,10 @@ public class ValueMappingMethod extends MappingMethod {
return first( getParameters() ); return first( getParameters() );
} }
public boolean isOverridden() {
return overridden;
}
public static class MappingEntry { public static class MappingEntry {
private final String source; private final String source;
private final String target; private final String target;

View File

@ -0,0 +1,48 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.internal.model.source;
import static org.mapstruct.ap.internal.util.Collections.first;
/**
* @author Filip Hrisafov
*/
public final class MappingMethodUtils {
/**
* Hide default constructor.
*/
private MappingMethodUtils() {
}
/**
* Checks if the provided {@code method} is for enum mapping. A Method is an Enum Mapping method when the
* source parameter and result type are enum types.
*
* @param method to check
*
* @return {@code true} if the method is for enum mapping, {@code false} otherwise
*/
public static boolean isEnumMapping(Method method) {
return method.getSourceParameters().size() == 1
&& first( method.getSourceParameters() ).getType().isEnumType()
&& method.getResultType().isEnumType();
}
}

View File

@ -381,9 +381,7 @@ public class SourceMethod implements Method {
public boolean isEnumMapping() { public boolean isEnumMapping() {
if ( isEnumMapping == null ) { if ( isEnumMapping == null ) {
isEnumMapping = getSourceParameters().size() == 1 isEnumMapping = MappingMethodUtils.isEnumMapping( this );
&& first( getSourceParameters() ).getType().isEnumType()
&& getResultType().isEnumType();
} }
return isEnumMapping; return isEnumMapping;
} }

View File

@ -317,7 +317,7 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Sourc
// prefer value mappings over enum mapping // prefer value mappings over enum mapping
ValueMappingMethod valueMappingMethod = new ValueMappingMethod.Builder() ValueMappingMethod valueMappingMethod = new ValueMappingMethod.Builder()
.mappingContext( mappingContext ) .mappingContext( mappingContext )
.souceMethod( method ) .method( method )
.valueMappings( mappingOptions.getValueMappings() ) .valueMappings( mappingOptions.getValueMappings() )
.build(); .build();
mappingMethods.add( valueMappingMethod ); mappingMethods.add( valueMappingMethod );

View File

@ -118,7 +118,7 @@ public enum Message {
VALUEMAPPING_DUPLICATE_SOURCE( "Source value mapping: \"%s\" cannot be mapped more than once." ), VALUEMAPPING_DUPLICATE_SOURCE( "Source value mapping: \"%s\" cannot be mapped more than once." ),
VALUEMAPPING_ANY_AREADY_DEFINED( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once." ), VALUEMAPPING_ANY_AREADY_DEFINED( "Source = \"<ANY_REMAINING>\" or \"<ANY_UNMAPPED>\" can only be used once." ),
VALUE_MAPPING_UNMAPPED_SOURCES( "The following constants from the source enum have no corresponding constant in the target enum and must be be mapped via adding additional mappings: %s." ), VALUE_MAPPING_UNMAPPED_SOURCES( "The following constants from the %s enum have no corresponding constant in the %s enum and must be be mapped via adding additional mappings: %s." ),
VALUEMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s." ); VALUEMAPPING_NON_EXISTING_CONSTANT( "Constant %s doesn't exist in enum type %s." );
// CHECKSTYLE:ON // CHECKSTYLE:ON

View File

@ -19,8 +19,8 @@
limitations under the License. limitations under the License.
--> -->
@Override <#if overridden>@Override</#if>
public <@includeModel object=returnType/> ${name}(<@includeModel object=sourceParameter/>) { <#lt>${accessibility.keyword} <@includeModel object=returnType/> ${name}(<@includeModel object=sourceParameter/>) {
<#list beforeMappingReferencesWithoutMappingTarget as callback> <#list beforeMappingReferencesWithoutMappingTarget as callback>
<@includeModel object=callback targetBeanName=resultName targetType=resultType/> <@includeModel object=callback targetBeanName=resultName targetType=resultType/>
<#if !callback_has_next> <#if !callback_has_next>

View File

@ -31,10 +31,12 @@ import org.mapstruct.ap.test.nestedbeans.erroneous.Cat;
import org.mapstruct.ap.test.nestedbeans.erroneous.CatDto; import org.mapstruct.ap.test.nestedbeans.erroneous.CatDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.Info; import org.mapstruct.ap.test.nestedbeans.erroneous.Info;
import org.mapstruct.ap.test.nestedbeans.erroneous.InfoDto; import org.mapstruct.ap.test.nestedbeans.erroneous.InfoDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.RoofTypeMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableCollectionElementPropertyMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableCollectionElementPropertyMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepListMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepListMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepMapKeyMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepMapKeyMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepMapValueMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepMapValueMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableEnumMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableValuePropertyMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableValuePropertyMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.UserDto; import org.mapstruct.ap.test.nestedbeans.erroneous.UserDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.User; import org.mapstruct.ap.test.nestedbeans.erroneous.User;
@ -42,11 +44,13 @@ import org.mapstruct.ap.test.nestedbeans.erroneous.WheelDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.Wheel; import org.mapstruct.ap.test.nestedbeans.erroneous.Wheel;
import org.mapstruct.ap.test.nestedbeans.erroneous.Car; import org.mapstruct.ap.test.nestedbeans.erroneous.Car;
import org.mapstruct.ap.test.nestedbeans.erroneous.CarDto; import org.mapstruct.ap.test.nestedbeans.erroneous.CarDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.ExternalRoofType;
import org.mapstruct.ap.test.nestedbeans.erroneous.House; import org.mapstruct.ap.test.nestedbeans.erroneous.House;
import org.mapstruct.ap.test.nestedbeans.erroneous.HouseDto; import org.mapstruct.ap.test.nestedbeans.erroneous.HouseDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.Color; import org.mapstruct.ap.test.nestedbeans.erroneous.Color;
import org.mapstruct.ap.test.nestedbeans.erroneous.ColorDto; import org.mapstruct.ap.test.nestedbeans.erroneous.ColorDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.Roof; import org.mapstruct.ap.test.nestedbeans.erroneous.Roof;
import org.mapstruct.ap.test.nestedbeans.erroneous.RoofType;
import org.mapstruct.ap.test.nestedbeans.erroneous.RoofDto; import org.mapstruct.ap.test.nestedbeans.erroneous.RoofDto;
import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepNestingMapper; import org.mapstruct.ap.test.nestedbeans.erroneous.UnmappableDeepNestingMapper;
import org.mapstruct.ap.test.nestedbeans.erroneous.Word; import org.mapstruct.ap.test.nestedbeans.erroneous.Word;
@ -60,6 +64,7 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
@WithClasses({ @WithClasses({
Car.class, CarDto.class, Color.class, ColorDto.class, Car.class, CarDto.class, Color.class, ColorDto.class,
House.class, HouseDto.class, Roof.class, RoofDto.class, House.class, HouseDto.class, Roof.class, RoofDto.class,
RoofType.class, ExternalRoofType.class, RoofTypeMapper.class,
User.class, UserDto.class, Wheel.class, WheelDto.class, User.class, UserDto.class, Wheel.class, WheelDto.class,
Dictionary.class, DictionaryDto.class, Word.class, WordDto.class, Dictionary.class, DictionaryDto.class, Word.class, WordDto.class,
ForeignWord.class, ForeignWordDto.class, ForeignWord.class, ForeignWordDto.class,
@ -183,4 +188,23 @@ public class DottedErrorMessageTest {
) )
public void testMapValueProperty() { public void testMapValueProperty() {
} }
@Test
@WithClasses({
UnmappableEnumMapper.class
})
@ExpectedCompilationOutcome(
value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = UnmappableEnumMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 26,
messageRegExp = "The following constants from the property \".*RoofType house\\.roof\\.type\" enum " +
"have no corresponding constant in the \".*ExternalRoofType house\\.roof\\.type\" enum and must " +
"be be mapped via adding additional mappings: NORMAL\\."
)
}
)
public void testMapEnumProperty() {
}
} }

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans;
/**
* @author Filip Hrisafov
*/
public enum ExternalRoofType {
OPEN, BOX, GAMBREL, STANDARD, NORMAL
}

View File

@ -18,17 +18,28 @@
*/ */
package org.mapstruct.ap.test.nestedbeans; package org.mapstruct.ap.test.nestedbeans;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.assertj.core.groups.Tuple;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import org.mapstruct.ap.testutil.runner.GeneratedSource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
@WithClasses({ @WithClasses({
User.class, UserDto.class, Car.class, CarDto.class, House.class, HouseDto.class, User.class, UserDto.class, Car.class, CarDto.class, House.class, HouseDto.class,
Wheel.class, WheelDto.class, Wheel.class, WheelDto.class,
Roof.class, RoofDto.class, Roof.class, RoofDto.class,
RoofType.class, ExternalRoofType.class,
org.mapstruct.ap.test.nestedbeans.other.CarDto.class, org.mapstruct.ap.test.nestedbeans.other.CarDto.class,
org.mapstruct.ap.test.nestedbeans.other.UserDto.class, org.mapstruct.ap.test.nestedbeans.other.UserDto.class,
org.mapstruct.ap.test.nestedbeans.other.HouseDto.class, org.mapstruct.ap.test.nestedbeans.other.HouseDto.class,
@ -41,6 +52,59 @@ import static org.assertj.core.api.Assertions.assertThat;
@RunWith(AnnotationProcessorTestRunner.class) @RunWith(AnnotationProcessorTestRunner.class)
public class NestedSimpleBeansMappingTest { public class NestedSimpleBeansMappingTest {
@Rule
public final GeneratedSource generatedSource = new GeneratedSource().addComparisonToFixtureFor(
UserDtoMapperClassic.class,
UserDtoMapperSmart.class,
UserDtoUpdateMapperSmart.class
);
/**
* Extracts all non synthetic declared fields from a class. This is needed, because jacoco adds a synthetic field
* to the classes and also assertj does not support testing that all fields are exactly there.
* This will be needed until <a href="https://github.com/joel-costigliola/assertj-core/issues/953">953</a> from
* assertj-core is implemented.
*
* @param clazz to extract from
*
* @return all the non synthetic declared fields
*/
private static List<Field> extractAllFields(Class<?> clazz) {
List<Field> nonSyntheticFields = new ArrayList<Field>();
for ( Field field : clazz.getDeclaredFields() ) {
if ( !field.isSynthetic() ) {
nonSyntheticFields.add( field );
}
}
return nonSyntheticFields;
}
@Test
public void shouldHaveAllFields() throws Exception {
// If this test fails that means something new was added to the structure of the User/UserDto.
// Make sure that the other tests are also updated (the new field is asserted)
Object[] userFields = new String[] { "name", "car", "secondCar", "house" };
assertThat( extractAllFields( User.class ) ).extracting( "name" ).containsExactlyInAnyOrder( userFields );
assertThat( extractAllFields( UserDto.class ) ).extracting( "name" ).containsExactlyInAnyOrder( userFields );
Object[] carFields = new String[] { "name", "year", "wheels" };
assertThat( extractAllFields( Car.class ) ).extracting( "name" ).containsExactlyInAnyOrder( carFields );
assertThat( extractAllFields( CarDto.class ) ).extracting( "name" ).containsExactlyInAnyOrder( carFields );
Object[] wheelFields = new String[] { "front", "right" };
assertThat( extractAllFields( Wheel.class ) ).extracting( "name" ).containsExactlyInAnyOrder( wheelFields );
assertThat( extractAllFields( WheelDto.class ) ).extracting( "name" ).containsExactlyInAnyOrder( wheelFields );
Object[] houseFields = new String[] { "name", "year", "roof" };
assertThat( extractAllFields( House.class ) ).extracting( "name" ).containsExactlyInAnyOrder( houseFields );
assertThat( extractAllFields( HouseDto.class ) ).extracting( "name" ).containsExactlyInAnyOrder( houseFields );
Object[] roofFields = new String[] { "color", "type" };
assertThat( extractAllFields( Roof.class ) ).extracting( "name" ).containsExactlyInAnyOrder( roofFields );
assertThat( extractAllFields( RoofDto.class ) ).extracting( "name" ).containsExactlyInAnyOrder( roofFields );
}
@Test @Test
public void shouldMapNestedBeans() { public void shouldMapNestedBeans() {
@ -49,11 +113,8 @@ public class NestedSimpleBeansMappingTest {
UserDto classicMapping = UserDtoMapperClassic.INSTANCE.userToUserDto( user ); UserDto classicMapping = UserDtoMapperClassic.INSTANCE.userToUserDto( user );
UserDto smartMapping = UserDtoMapperSmart.INSTANCE.userToUserDto( user ); UserDto smartMapping = UserDtoMapperSmart.INSTANCE.userToUserDto( user );
System.out.println( smartMapping ); assertUserDto( classicMapping, user );
System.out.println( classicMapping ); assertUserDto( smartMapping, user );
assertThat( smartMapping ).isNotNull();
assertThat( smartMapping ).isEqualTo( classicMapping );
} }
@Test @Test
@ -67,15 +128,58 @@ public class NestedSimpleBeansMappingTest {
smartMapping.setCar( new CarDto() ); smartMapping.setCar( new CarDto() );
smartMapping.getCar().setName( "Toyota" ); smartMapping.getCar().setName( "Toyota" );
// create a classic mapping and adapt expected result to Toyota
UserDto classicMapping = UserDtoMapperClassic.INSTANCE.userToUserDto( TestData.createUser() );
classicMapping.getCar().setName( "Toyota" );
// action // action
UserDtoUpdateMapperSmart.INSTANCE.userToUserDto( smartMapping, user ); UserDtoUpdateMapperSmart.INSTANCE.userToUserDto( smartMapping, user );
// result // result
assertThat( smartMapping ).isNotNull(); assertThat( smartMapping.getName() ).isEqualTo( user.getName() );
assertThat( smartMapping ).isEqualTo( classicMapping ); assertThat( smartMapping.getCar().getYear() ).isEqualTo( user.getCar().getYear() );
assertThat( smartMapping.getCar().getName() ).isEqualTo( "Toyota" );
assertThat( user.getCar().getName() ).isNull();
assertWheels( smartMapping.getCar().getWheels(), user.getCar().getWheels() );
assertCar( smartMapping.getSecondCar(), user.getSecondCar() );
assertHouse( smartMapping.getHouse(), user.getHouse() );
}
private static void assertUserDto(UserDto userDto, User user) {
assertThat( userDto ).isNotNull();
assertThat( userDto.getName() ).isEqualTo( user.getName() );
assertCar( userDto.getCar(), user.getCar() );
assertCar( userDto.getSecondCar(), user.getSecondCar() );
assertHouse( userDto.getHouse(), user.getHouse() );
}
private static void assertCar(CarDto carDto, Car car) {
if ( car == null ) {
assertThat( carDto ).isNull();
}
else {
assertThat( carDto.getName() ).isEqualTo( car.getName() );
assertThat( carDto.getYear() ).isEqualTo( car.getYear() );
assertWheels( carDto.getWheels(), car.getWheels() );
}
}
private static void assertWheels(List<WheelDto> wheelDtos, List<Wheel> wheels) {
List<Tuple> wheelTuples = wheels.stream().map( new Function<Wheel, Tuple>() {
@Override
public Tuple apply(Wheel wheel) {
return tuple( wheel.isFront(), wheel.isRight() );
}
} ).collect( Collectors.<Tuple>toList() );
assertThat( wheelDtos )
.extracting( "front", "right" )
.containsExactlyElementsOf( wheelTuples );
}
private static void assertHouse(HouseDto houseDto, House house) {
assertThat( houseDto.getName() ).isEqualTo( house.getName() );
assertThat( houseDto.getYear() ).isEqualTo( house.getYear() );
assertRoof( houseDto.getRoof(), house.getRoof() );
}
private static void assertRoof(RoofDto roofDto, Roof roof) {
assertThat( roofDto.getColor() ).isEqualTo( String.valueOf( roof.getColor() ) );
assertThat( roofDto.getType().name() ).isEqualTo( roof.getType().name() );
} }
} }

View File

@ -20,12 +20,14 @@ package org.mapstruct.ap.test.nestedbeans;
public class Roof { public class Roof {
private int color; private int color;
private RoofType type;
public Roof() { public Roof() {
} }
public Roof(int color) { public Roof(int color, RoofType type) {
this.color = color; this.color = color;
this.type = type;
} }
public int getColor() { public int getColor() {
@ -40,7 +42,16 @@ public class Roof {
public String toString() { public String toString() {
return "Roof{" + return "Roof{" +
"color='" + color + '\'' + "color='" + color + '\'' +
"type='" + type + '\'' +
'}'; '}';
} }
public RoofType getType() {
return type;
}
public Roof setType(RoofType type) {
this.type = type;
return this;
}
} }

View File

@ -20,6 +20,7 @@ package org.mapstruct.ap.test.nestedbeans;
public class RoofDto { public class RoofDto {
private String color; private String color;
private ExternalRoofType type;
public RoofDto() { public RoofDto() {
} }
@ -36,6 +37,15 @@ public class RoofDto {
this.color = color; this.color = color;
} }
public ExternalRoofType getType() {
return type;
}
public RoofDto setType(ExternalRoofType type) {
this.type = type;
return this;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if ( this == o ) { if ( this == o ) {
@ -47,20 +57,26 @@ public class RoofDto {
RoofDto roofDto = (RoofDto) o; RoofDto roofDto = (RoofDto) o;
if ( type != ( (RoofDto) o ).type ) {
return false;
}
return color != null ? color.equals( roofDto.color ) : roofDto.color == null; return color != null ? color.equals( roofDto.color ) : roofDto.color == null;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return color != null ? color.hashCode() : 0; int result = color != null ? color.hashCode() : 0;
result = 31 * result + ( type != null ? type.hashCode() : 0 );
return result;
} }
@Override @Override
public String toString() { public String toString() {
return "RoofDto{" + return "RoofDto{" +
"color='" + color + '\'' + "color='" + color + '\'' +
"type='" + type + '\'' +
'}'; '}';
} }
} }

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans;
/**
* @author Filip Hrisafov
*/
public enum RoofType {
OPEN, BOX, GAMBREL
}

View File

@ -33,7 +33,7 @@ public class TestData {
new Wheel().rear().left(), new Wheel().rear().left(),
new Wheel().rear().right() new Wheel().rear().right()
) ), ) ),
new House( "Black", 1834, new Roof( 1 ) ) new House( "Black", 1834, new Roof( 1, RoofType.BOX ) )
); );
} }

View File

@ -40,4 +40,6 @@ public interface UserDtoMapperClassic {
WheelDto mapWheel(Wheel wheels); WheelDto mapWheel(Wheel wheels);
ExternalRoofType mapRoofType(RoofType roofType);
} }

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans.erroneous;
/**
* @author Filip Hrisafov
*/
public enum ExternalRoofType {
OPEN, BOX, GAMBREL, STANDARD
}

View File

@ -20,6 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
public class Roof { public class Roof {
private Color color; private Color color;
private RoofType type;
public Color getColor() { public Color getColor() {
return color; return color;
@ -28,4 +29,13 @@ public class Roof {
public void setColor(Color color) { public void setColor(Color color) {
this.color = color; this.color = color;
} }
public RoofType getType() {
return type;
}
public Roof setType(RoofType type) {
this.type = type;
return this;
}
} }

View File

@ -20,6 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
public class RoofDto { public class RoofDto {
private ColorDto color; private ColorDto color;
private ExternalRoofType type;
public ColorDto getColor() { public ColorDto getColor() {
return color; return color;
@ -28,4 +29,12 @@ public class RoofDto {
public void setColor(ColorDto color) { public void setColor(ColorDto color) {
this.color = color; this.color = color;
} }
public ExternalRoofType getType() {
return type;
}
public void setType(ExternalRoofType type) {
this.type = type;
}
} }

View File

@ -0,0 +1,28 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans.erroneous;
/**
* @author Filip Hrisafov
*/
public enum RoofType {
OPEN, BOX, GAMBREL, NORMAL
}

View File

@ -0,0 +1,32 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
/**
* @author Filip Hrisafov
*/
@Mapper
public interface RoofTypeMapper {
@ValueMapping( source = "NORMAL", target = "STANDARD")
ExternalRoofType map(RoofType type);
}

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableCollectionElementPropertyMapper { public abstract class UnmappableCollectionElementPropertyMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableDeepListMapper { public abstract class UnmappableDeepListMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableDeepMapKeyMapper { public abstract class UnmappableDeepMapKeyMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableDeepMapValueMapper { public abstract class UnmappableDeepMapValueMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableDeepNestingMapper { public abstract class UnmappableDeepNestingMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -0,0 +1,47 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper;
@Mapper
public abstract class UnmappableEnumMapper {
abstract UserDto userToUserDto(User user);
public ColorDto map(Color color) {
return new ColorDto();
}
public CarDto map(Car carDto) {
return new CarDto();
}
public DictionaryDto map(Dictionary dictionary) {
return new DictionaryDto();
}
public ComputerDto map(Computer computer) {
return new ComputerDto();
}
public CatDto map(Cat cat) {
return new CatDto();
}
}

View File

@ -20,7 +20,7 @@ package org.mapstruct.ap.test.nestedbeans.erroneous;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@Mapper @Mapper(uses = RoofTypeMapper.class)
public abstract class UnmappableValuePropertyMapper { public abstract class UnmappableValuePropertyMapper {
abstract UserDto userToUserDto(User user); abstract UserDto userToUserDto(User user);

View File

@ -0,0 +1,143 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2017-03-01T22:15:21+0100",
comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)"
)
public class UserDtoMapperClassicImpl implements UserDtoMapperClassic {
@Override
public UserDto userToUserDto(User user) {
if ( user == null ) {
return null;
}
UserDto userDto = new UserDto();
userDto.setName( user.getName() );
userDto.setCar( carToCarDto( user.getCar() ) );
userDto.setSecondCar( carToCarDto( user.getSecondCar() ) );
userDto.setHouse( houseToHouseDto( user.getHouse() ) );
return userDto;
}
@Override
public CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setName( car.getName() );
carDto.setYear( car.getYear() );
List<WheelDto> list = mapWheels( car.getWheels() );
if ( list != null ) {
carDto.setWheels( list );
}
return carDto;
}
@Override
public HouseDto houseToHouseDto(House house) {
if ( house == null ) {
return null;
}
HouseDto houseDto = new HouseDto();
houseDto.setName( house.getName() );
houseDto.setYear( house.getYear() );
houseDto.setRoof( roofToRoofDto( house.getRoof() ) );
return houseDto;
}
@Override
public RoofDto roofToRoofDto(Roof roof) {
if ( roof == null ) {
return null;
}
RoofDto roofDto = new RoofDto();
roofDto.setColor( String.valueOf( roof.getColor() ) );
roofDto.setType( mapRoofType( roof.getType() ) );
return roofDto;
}
@Override
public List<WheelDto> mapWheels(List<Wheel> wheels) {
if ( wheels == null ) {
return null;
}
List<WheelDto> list = new ArrayList<WheelDto>();
for ( Wheel wheel : wheels ) {
list.add( mapWheel( wheel ) );
}
return list;
}
@Override
public WheelDto mapWheel(Wheel wheels) {
if ( wheels == null ) {
return null;
}
WheelDto wheelDto = new WheelDto();
wheelDto.setFront( wheels.isFront() );
wheelDto.setRight( wheels.isRight() );
return wheelDto;
}
@Override
public ExternalRoofType mapRoofType(RoofType roofType) {
if ( roofType == null ) {
return null;
}
ExternalRoofType externalRoofType;
switch ( roofType ) {
case OPEN: externalRoofType = ExternalRoofType.OPEN;
break;
case BOX: externalRoofType = ExternalRoofType.BOX;
break;
case GAMBREL: externalRoofType = ExternalRoofType.GAMBREL;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + roofType );
}
return externalRoofType;
}
}

View File

@ -0,0 +1,221 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2017-03-01T22:15:23+0100",
comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)"
)
public class UserDtoMapperSmartImpl implements UserDtoMapperSmart {
@Override
public UserDto userToUserDto(User user) {
if ( user == null ) {
return null;
}
UserDto userDto = new UserDto();
userDto.setName( user.getName() );
userDto.setCar( carToCarDto( user.getCar() ) );
userDto.setSecondCar( carToCarDto( user.getSecondCar() ) );
userDto.setHouse( houseToHouseDto( user.getHouse() ) );
return userDto;
}
@Override
public org.mapstruct.ap.test.nestedbeans.other.UserDto userToUserDto2(User user) {
if ( user == null ) {
return null;
}
org.mapstruct.ap.test.nestedbeans.other.UserDto userDto = new org.mapstruct.ap.test.nestedbeans.other.UserDto();
userDto.setName( user.getName() );
userDto.setCar( carToCarDto1( user.getCar() ) );
userDto.setHouse( houseToHouseDto1( user.getHouse() ) );
return userDto;
}
protected WheelDto wheelToWheelDto(Wheel wheel) {
if ( wheel == null ) {
return null;
}
WheelDto wheelDto = new WheelDto();
wheelDto.setFront( wheel.isFront() );
wheelDto.setRight( wheel.isRight() );
return wheelDto;
}
protected List<WheelDto> wheelListToWheelDtoList(List<Wheel> list) {
if ( list == null ) {
return null;
}
List<WheelDto> list1 = new ArrayList<WheelDto>();
for ( Wheel wheel : list ) {
list1.add( wheelToWheelDto( wheel ) );
}
return list1;
}
protected CarDto carToCarDto(Car car) {
if ( car == null ) {
return null;
}
CarDto carDto = new CarDto();
carDto.setName( car.getName() );
carDto.setYear( car.getYear() );
List<WheelDto> list = wheelListToWheelDtoList( car.getWheels() );
if ( list != null ) {
carDto.setWheels( list );
}
return carDto;
}
protected ExternalRoofType roofTypeToExternalRoofType(RoofType roofType) {
if ( roofType == null ) {
return null;
}
ExternalRoofType externalRoofType;
switch ( roofType ) {
case OPEN: externalRoofType = ExternalRoofType.OPEN;
break;
case BOX: externalRoofType = ExternalRoofType.BOX;
break;
case GAMBREL: externalRoofType = ExternalRoofType.GAMBREL;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + roofType );
}
return externalRoofType;
}
protected RoofDto roofToRoofDto(Roof roof) {
if ( roof == null ) {
return null;
}
RoofDto roofDto = new RoofDto();
roofDto.setColor( String.valueOf( roof.getColor() ) );
roofDto.setType( roofTypeToExternalRoofType( roof.getType() ) );
return roofDto;
}
protected HouseDto houseToHouseDto(House house) {
if ( house == null ) {
return null;
}
HouseDto houseDto = new HouseDto();
houseDto.setName( house.getName() );
houseDto.setYear( house.getYear() );
houseDto.setRoof( roofToRoofDto( house.getRoof() ) );
return houseDto;
}
protected org.mapstruct.ap.test.nestedbeans.other.WheelDto wheelToWheelDto1(Wheel wheel) {
if ( wheel == null ) {
return null;
}
org.mapstruct.ap.test.nestedbeans.other.WheelDto wheelDto = new org.mapstruct.ap.test.nestedbeans.other.WheelDto();
wheelDto.setFront( wheel.isFront() );
wheelDto.setRight( wheel.isRight() );
return wheelDto;
}
protected List<org.mapstruct.ap.test.nestedbeans.other.WheelDto> wheelListToWheelDtoList1(List<Wheel> list) {
if ( list == null ) {
return null;
}
List<org.mapstruct.ap.test.nestedbeans.other.WheelDto> list1 = new ArrayList<org.mapstruct.ap.test.nestedbeans.other.WheelDto>();
for ( Wheel wheel : list ) {
list1.add( wheelToWheelDto1( wheel ) );
}
return list1;
}
protected org.mapstruct.ap.test.nestedbeans.other.CarDto carToCarDto1(Car car) {
if ( car == null ) {
return null;
}
org.mapstruct.ap.test.nestedbeans.other.CarDto carDto = new org.mapstruct.ap.test.nestedbeans.other.CarDto();
carDto.setName( car.getName() );
carDto.setYear( car.getYear() );
List<org.mapstruct.ap.test.nestedbeans.other.WheelDto> list = wheelListToWheelDtoList1( car.getWheels() );
if ( list != null ) {
carDto.setWheels( list );
}
return carDto;
}
protected org.mapstruct.ap.test.nestedbeans.other.RoofDto roofToRoofDto1(Roof roof) {
if ( roof == null ) {
return null;
}
org.mapstruct.ap.test.nestedbeans.other.RoofDto roofDto = new org.mapstruct.ap.test.nestedbeans.other.RoofDto();
roofDto.setColor( String.valueOf( roof.getColor() ) );
return roofDto;
}
protected org.mapstruct.ap.test.nestedbeans.other.HouseDto houseToHouseDto1(House house) {
if ( house == null ) {
return null;
}
org.mapstruct.ap.test.nestedbeans.other.HouseDto houseDto = new org.mapstruct.ap.test.nestedbeans.other.HouseDto();
houseDto.setName( house.getName() );
houseDto.setYear( house.getYear() );
houseDto.setRoof( roofToRoofDto1( house.getRoof() ) );
return houseDto;
}
}

View File

@ -0,0 +1,170 @@
/**
* Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
* and/or other contributors as indicated by the @authors tag. See the
* copyright.txt file in the distribution for a full listing of all
* contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapstruct.ap.test.nestedbeans;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2017-03-01T22:15:22+0100",
comments = "version: , compiler: javac, environment: Java 1.8.0_112 (Oracle Corporation)"
)
public class UserDtoUpdateMapperSmartImpl implements UserDtoUpdateMapperSmart {
@Override
public void userToUserDto(UserDto userDto, User user) {
if ( user == null ) {
return;
}
if ( user.getName() != null ) {
userDto.setName( user.getName() );
}
if ( user.getCar() != null ) {
if ( userDto.getCar() == null ) {
userDto.setCar( new CarDto() );
}
carToCarDto( user.getCar(), userDto.getCar() );
}
else {
userDto.setCar( null );
}
if ( user.getSecondCar() != null ) {
if ( userDto.getSecondCar() == null ) {
userDto.setSecondCar( new CarDto() );
}
carToCarDto( user.getSecondCar(), userDto.getSecondCar() );
}
else {
userDto.setSecondCar( null );
}
if ( user.getHouse() != null ) {
if ( userDto.getHouse() == null ) {
userDto.setHouse( new HouseDto() );
}
houseToHouseDto( user.getHouse(), userDto.getHouse() );
}
else {
userDto.setHouse( null );
}
}
protected WheelDto wheelToWheelDto(Wheel wheel) {
if ( wheel == null ) {
return null;
}
WheelDto wheelDto = new WheelDto();
wheelDto.setFront( wheel.isFront() );
wheelDto.setRight( wheel.isRight() );
return wheelDto;
}
protected List<WheelDto> wheelListToWheelDtoList(List<Wheel> list) {
if ( list == null ) {
return null;
}
List<WheelDto> list1 = new ArrayList<WheelDto>();
for ( Wheel wheel : list ) {
list1.add( wheelToWheelDto( wheel ) );
}
return list1;
}
protected void carToCarDto(Car car, CarDto mappingTarget) {
if ( car == null ) {
return;
}
if ( car.getName() != null ) {
mappingTarget.setName( car.getName() );
}
mappingTarget.setYear( car.getYear() );
if ( mappingTarget.getWheels() != null ) {
List<WheelDto> list = wheelListToWheelDtoList( car.getWheels() );
if ( list != null ) {
mappingTarget.getWheels().clear();
mappingTarget.getWheels().addAll( list );
}
}
else {
List<WheelDto> list = wheelListToWheelDtoList( car.getWheels() );
if ( list != null ) {
mappingTarget.setWheels( list );
}
}
}
protected ExternalRoofType roofTypeToExternalRoofType(RoofType roofType) {
if ( roofType == null ) {
return null;
}
ExternalRoofType externalRoofType;
switch ( roofType ) {
case OPEN: externalRoofType = ExternalRoofType.OPEN;
break;
case BOX: externalRoofType = ExternalRoofType.BOX;
break;
case GAMBREL: externalRoofType = ExternalRoofType.GAMBREL;
break;
default: throw new IllegalArgumentException( "Unexpected enum constant: " + roofType );
}
return externalRoofType;
}
protected void roofToRoofDto(Roof roof, RoofDto mappingTarget) {
if ( roof == null ) {
return;
}
mappingTarget.setColor( String.valueOf( roof.getColor() ) );
if ( roof.getType() != null ) {
mappingTarget.setType( roofTypeToExternalRoofType( roof.getType() ) );
}
}
protected void houseToHouseDto(House house, HouseDto mappingTarget) {
if ( house == null ) {
return;
}
if ( house.getName() != null ) {
mappingTarget.setName( house.getName() );
}
mappingTarget.setYear( house.getYear() );
if ( house.getRoof() != null ) {
if ( mappingTarget.getRoof() == null ) {
mappingTarget.setRoof( new RoofDto() );
}
roofToRoofDto( house.getRoof(), mappingTarget.getRoof() );
}
else {
mappingTarget.setRoof( null );
}
}
}