Permalink
Browse files

#1001 auto mapping support for update methods

  • Loading branch information...
1 parent 5cb80cb commit 0188dcbdcc1dfa0b2fceb46b9f916e333601aedf @sjaakd sjaakd committed Jan 8, 2017
@@ -635,14 +635,24 @@ private Assignment forgeMapping(SourceRHS sourceRHS) {
if ( sourceType.isPrimitive() || targetType.isPrimitive() ) {
return null;
}
+
String name = getName( sourceType, targetType );
+ List<Parameter> parameters = new ArrayList( method.getContextParameters() );
+ Type returnType;
+ if ( method.isUpdateMethod() ) {
+ parameters.add( Parameter.forForgedMappingTarget( targetType ) );
+ returnType = ctx.getTypeFactory().createVoidType();
+ }
+ else {
+ returnType = targetType;
+ }
ForgedMethod forgedMethod = new ForgedMethod(
name,
sourceType,
- targetType,
+ returnType,
method.getMapperConfiguration(),
method.getExecutable(),
- method.getContextParameters(),
+ parameters,
getForgedMethodHistory( sourceRHS )
);
@@ -125,6 +125,15 @@ public static Parameter forElementAndType(VariableElement element, Type paramete
ContextPrism.getInstanceOn( element ) != null );
}
+ public static Parameter forForgedMappingTarget(Type parameterType) {
+ return new Parameter(
+ "mappingTarget",
+ parameterType,
+ true,
+ false,
+ false);
+ }
+
/**
* @param parameters the parameters to filter
* @return the parameters from the given list that are considered 'source parameters'
@@ -156,4 +165,24 @@ public static Parameter forElementAndType(VariableElement element, Type paramete
return contextParameters;
}
+
+ public static Parameter getMappingTargetParameter(List<Parameter> parameters) {
+ for ( Parameter parameter : parameters ) {
+ if ( parameter.isMappingTarget() ) {
+ return parameter;
+ }
+ }
+
+ return null;
+ }
+
+ public static Parameter getTargetTypeParameter(List<Parameter> parameters) {
+ for ( Parameter parameter : parameters ) {
+ if ( parameter.isTargetType() ) {
+ return parameter;
+ }
+ }
+
+ return null;
+ }
}
@@ -494,6 +494,15 @@ else if ( collectionOrMap.isMapType()
}
/**
+ * creates a void return type
+ *
+ * @return void type
+ */
+ public Type createVoidType() {
+ return getType( typeUtils.getNoType( TypeKind.VOID ) );
+ }
+
+ /**
* Establishes the type bound:
* <ol>
* <li>{@code<? extends Number>}, returns Number</li>
@@ -47,34 +47,35 @@
private final List<Parameter> sourceParameters;
private final List<Parameter> contextParameters;
+ private final Parameter mappingTargetParameter;
/**
* Creates a new forged method with the given name.
*
* @param name the (unique name) for this method
* @param sourceType the source type
- * @param targetType the target type.
+ * @param returnType the return type.
* @param mapperConfiguration the mapper configuration
* @param positionHintElement element used to for reference to the position in the source file.
* @param additionalParameters additional parameters to add to the forged method
*/
- public ForgedMethod(String name, Type sourceType, Type targetType, MapperConfiguration mapperConfiguration,
+ public ForgedMethod(String name, Type sourceType, Type returnType, MapperConfiguration mapperConfiguration,
ExecutableElement positionHintElement, List<Parameter> additionalParameters) {
- this( name, sourceType, targetType, mapperConfiguration, positionHintElement, additionalParameters, null );
+ this( name, sourceType, returnType, mapperConfiguration, positionHintElement, additionalParameters, null );
}
/**
* Creates a new forged method with the given name.
*
* @param name the (unique name) for this method
* @param sourceType the source type
- * @param targetType the target type.
+ * @param returnType the return type.
* @param mapperConfiguration the mapper configuration
* @param positionHintElement element used to for reference to the position in the source file.
* @param additionalParameters additional parameters to add to the forged method
* @param history a parent forged method if this is a forged method within a forged method
*/
- public ForgedMethod(String name, Type sourceType, Type targetType, MapperConfiguration mapperConfiguration,
+ public ForgedMethod(String name, Type sourceType, Type returnType, MapperConfiguration mapperConfiguration,
ExecutableElement positionHintElement, List<Parameter> additionalParameters,
ForgedMethodHistory history) {
String sourceParamName = Strings.decapitalize( sourceType.getName() );
@@ -85,8 +86,9 @@ public ForgedMethod(String name, Type sourceType, Type targetType, MapperConfigu
this.parameters.addAll( additionalParameters );
this.sourceParameters = Parameter.getSourceParameters( parameters );
this.contextParameters = Parameter.getContextParameters( parameters );
+ this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
- this.returnType = targetType;
+ this.returnType = returnType;
this.thrownTypes = new ArrayList<Type>();
this.name = Strings.sanitizeIdentifierName( name );
this.mapperConfiguration = mapperConfiguration;
@@ -109,6 +111,7 @@ public ForgedMethod(String name, ForgedMethod forgedMethod) {
this.sourceParameters = Parameter.getSourceParameters( parameters );
this.contextParameters = Parameter.getContextParameters( parameters );
+ this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
this.name = name;
}
@@ -165,7 +168,7 @@ public String getName() {
@Override
public Parameter getMappingTargetParameter() {
- return null;
+ return mappingTargetParameter;
}
@Override
@@ -203,7 +206,7 @@ public void addThrownTypes(List<Type> thrownTypesToAdd) {
@Override
public Type getResultType() {
- return returnType;
+ return mappingTargetParameter != null ? mappingTargetParameter.getType() : returnType;
}
@Override
@@ -303,4 +306,5 @@ public int hashCode() {
result = 31 * result + ( name != null ? name.hashCode() : 0 );
return result;
}
+
}
@@ -228,8 +228,8 @@ private SourceMethod(Type declaringMapper, ExecutableElement executable, List<Pa
this.sourceParameters = Parameter.getSourceParameters( parameters );
this.contextParameters = Parameter.getContextParameters( parameters );
- this.mappingTargetParameter = determineMappingTargetParameter( parameters );
- this.targetTypeParameter = determineTargetTypeParameter( parameters );
+ this.mappingTargetParameter = Parameter.getMappingTargetParameter( parameters );
+ this.targetTypeParameter = Parameter.getTargetTypeParameter( parameters );
this.isObjectFactory = determineIfIsObjectFactory( executable );
this.typeUtils = typeUtils;
@@ -248,26 +248,6 @@ private boolean determineIfIsObjectFactory(ExecutableElement executable) {
&& ( hasFactoryAnnotation || hasNoSourceParameters );
}
- private Parameter determineMappingTargetParameter(Iterable<Parameter> parameters) {
- for ( Parameter parameter : parameters ) {
- if ( parameter.isMappingTarget() ) {
- return parameter;
- }
- }
-
- return null;
- }
-
- private Parameter determineTargetTypeParameter(Iterable<Parameter> parameters) {
- for ( Parameter parameter : parameters ) {
- if ( parameter.isTargetType() ) {
- return parameter;
- }
- }
-
- return null;
- }
-
@Override
public Type getDeclaringMapper() {
return declaringMapper;
@@ -30,7 +30,8 @@
Wheel.class, WheelDto.class,
Roof.class, RoofDto.class,
UserDtoMapperClassic.class,
- UserDtoMapperSmart.class
+ UserDtoMapperSmart.class,
+ UserDtoUpdateMapperSmart.class
})
@RunWith(AnnotationProcessorTestRunner.class)
public class NestedSimpleBeansMappingTest {
@@ -46,9 +47,30 @@ public void shouldMapNestedBeans() {
System.out.println( smartMapping );
System.out.println( classicMapping );
-
assertThat( smartMapping ).isNotNull();
assertThat( smartMapping ).isEqualTo( classicMapping );
}
+ @Test
+ public void shouldMapUpdateNestedBeans() {
+
+ User user = TestData.createUser();
+ user.getCar().setName( null );
+
+ // create a pre-exsiting smartMapping
+ UserDto smartMapping = new UserDto();
+ smartMapping.setCar( new CarDto() );
+ 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
+ UserDtoUpdateMapperSmart.INSTANCE.userToUserDto( smartMapping, user );
+
+ // result
+ assertThat( smartMapping ).isNotNull();
+ assertThat( smartMapping ).isEqualTo( classicMapping );
+ }
}
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mapstruct.ap.test.nestedbeans;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.NullValueCheckStrategy;
+import org.mapstruct.factory.Mappers;
+
+@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
+public interface UserDtoUpdateMapperSmart {
+
+ UserDtoUpdateMapperSmart INSTANCE = Mappers.getMapper( UserDtoUpdateMapperSmart.class );
+
+ void userToUserDto(@MappingTarget UserDto userDto, User user);
+
+}

0 comments on commit 0188dcb

Please sign in to comment.