diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java index 9edbcdf5d..c43570432 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/PropertyMapping.java @@ -170,8 +170,7 @@ public class PropertyMapping extends ModelElement { // all the tricky cases will be excluded for the time being. boolean preferUpdateMethods; - if ( targetType.isCollectionOrMapType() || targetType.isArrayType() || - targetAccessorType == TargetWriteAccessorType.ADDER ) { + if ( targetAccessorType == TargetWriteAccessorType.ADDER ) { preferUpdateMethods = false; } else { @@ -253,7 +252,8 @@ public class PropertyMapping extends ModelElement { } Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null, null ); - result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod ); + result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod, + targetType.getImplementationType() ); } else { result = new SetterWrapper( result, method.getThrownTypes() ); @@ -312,16 +312,29 @@ public class PropertyMapping extends ModelElement { newCollectionOrMap = new NewCollectionOrMapWrapper( result, implementationTypes ); newCollectionOrMap = new SetterWrapper( newCollectionOrMap, method.getThrownTypes() ); } + if ( result.isUpdateMethod() ) { + if ( targetReadAccessor == null ) { + ctx.getMessager().printMessage( method.getExecutable(), + Message.PROPERTYMAPPING_NO_READ_ACCESSOR_FOR_TARGET_TYPE, + targetPropertyName ); + } + Assignment factoryMethod + = ctx.getMappingResolver().getFactoryMethod( method, targetType, null, null ); + result = new UpdateWrapper( result, method.getThrownTypes(), factoryMethod, + targetType.getImplementationType() ); + } + else { + // wrap the assignment in the setter method + result = new SetterWrapper( result, method.getThrownTypes() ); - // wrap the assignment in the setter method - result = new SetterWrapper( result, method.getThrownTypes() ); + // target accessor is setter, so wrap the setter in setter map/ collection handling + result = new SetterWrapperForCollectionsAndMaps( + result, + targetWriteAccessor, + newCollectionOrMap + ); + } - // target accessor is setter, so wrap the setter in setter map/ collection handling - result = new SetterWrapperForCollectionsAndMaps( - result, - targetWriteAccessor, - newCollectionOrMap - ); } else { // target accessor is getter, so wrap the setter in getter map/ collection handling @@ -589,7 +602,8 @@ public class PropertyMapping extends ModelElement { } Assignment factoryMethod = ctx.getMappingResolver().getFactoryMethod( method, targetType, null, null ); - assignment = new UpdateWrapper( assignment, method.getThrownTypes(), factoryMethod ); + assignment = new UpdateWrapper( assignment, method.getThrownTypes(), factoryMethod, + targetType.getImplementationType() ); } else { assignment = new SetterWrapper( assignment, method.getThrownTypes() ); diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java index ff025035a..dd70f119a 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.java @@ -19,7 +19,9 @@ package org.mapstruct.ap.internal.model.assignment; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.mapstruct.ap.internal.model.common.Type; @@ -32,11 +34,14 @@ public class UpdateWrapper extends AssignmentWrapper { private final List thrownTypesToExclude; private final Assignment factoryMethod; + private final Type targetImplementationType; - public UpdateWrapper(Assignment decoratedAssignment, List thrownTypesToExclude, Assignment factoryMethod ) { + public UpdateWrapper(Assignment decoratedAssignment, List thrownTypesToExclude, Assignment factoryMethod, + Type targetImplementationType ) { super( decoratedAssignment ); this.thrownTypesToExclude = thrownTypesToExclude; this.factoryMethod = factoryMethod; + this.targetImplementationType = targetImplementationType; } @Override @@ -53,6 +58,16 @@ public class UpdateWrapper extends AssignmentWrapper { return result; } + @Override + public Set getImportTypes() { + Set imported = new HashSet(); + imported.addAll( super.getImportTypes() ); + if ( targetImplementationType != null ) { + imported.add( targetImplementationType ); + } + return imported; + } + public Assignment getFactoryMethod() { return factoryMethod; } diff --git a/processor/src/main/resources/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.ftl b/processor/src/main/resources/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.ftl index 0a0921317..563e4522e 100644 --- a/processor/src/main/resources/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.ftl +++ b/processor/src/main/resources/org/mapstruct/ap/internal/model/assignment/UpdateWrapper.ftl @@ -32,7 +32,7 @@ <#macro _assignment> if ( ${ext.targetBeanName}.${ext.targetReadAccessorName}() == null ) { - ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <#if factoryMethod??><@includeModel object=factoryMethod targetType=ext.targetType/><#else>new <@includeModel object=ext.targetType/>() ); + ${ext.targetBeanName}.${ext.targetWriteAccessorName}( <#if factoryMethod??><@includeModel object=factoryMethod targetType=ext.targetType/><#else><@_newObject/> ); } <@includeModel object=assignment targetBeanName=ext.targetBeanName @@ -40,4 +40,6 @@ targetReadAccessorName=ext.targetReadAccessorName targetWriteAccessorName=ext.targetWriteAccessorName targetType=ext.targetType/> - \ No newline at end of file + +<#macro _newObject>new <#if ext.targetType.implementationType??><@includeModel object=ext.targetType.implementationType/><#else><@includeModel object=ext.targetType/>() + diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/CompanyMapper.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/CompanyMapper.java index 69936bc9a..b8bdf8001 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/CompanyMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/CompanyMapper.java @@ -19,7 +19,9 @@ package org.mapstruct.ap.test.updatemethods; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** @@ -35,6 +37,10 @@ public interface CompanyMapper { DepartmentInBetween toInBetween(DepartmentDto dto); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) void toDepartmentEntity(DepartmentInBetween dto, @MappingTarget DepartmentEntity entity); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentDto.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentDto.java index 193032ae2..38f1174a6 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentDto.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentDto.java @@ -18,6 +18,9 @@ */ package org.mapstruct.ap.test.updatemethods; +import java.util.List; +import java.util.Map; + /** * * @author Sjaak Derksen @@ -25,6 +28,8 @@ package org.mapstruct.ap.test.updatemethods; public class DepartmentDto { private String name; + private List employees; + private Map secretaryToEmployee; public String getName() { return name; @@ -34,4 +39,20 @@ public class DepartmentDto { this.name = name; } + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } + + public Map getSecretaryToEmployee() { + return secretaryToEmployee; + } + + public void setSecretaryToEmployee(Map secretaryToEmployee) { + this.secretaryToEmployee = secretaryToEmployee; + } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentEntity.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentEntity.java index b0b70b075..302573f85 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentEntity.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/DepartmentEntity.java @@ -18,6 +18,9 @@ */ package org.mapstruct.ap.test.updatemethods; +import java.util.List; +import java.util.Map; + /** * * @author Sjaak Derksen @@ -25,6 +28,8 @@ package org.mapstruct.ap.test.updatemethods; public class DepartmentEntity { private String name; + private List employees; + private Map secretaryToEmployee; public DepartmentEntity(Integer justAnArgToAvoidConstruction) { } @@ -37,4 +42,20 @@ public class DepartmentEntity { this.name = name; } + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } + + public Map getSecretaryToEmployee() { + return secretaryToEmployee; + } + + public void setSecretaryToEmployee(Map secretaryToEmployee) { + this.secretaryToEmployee = secretaryToEmployee; + } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeDto.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeDto.java new file mode 100644 index 000000000..5cfc7c4a3 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeDto.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.updatemethods; + +/** + * + * @author Sjaak Derksen + */ +public class EmployeeDto { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeEntity.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeEntity.java new file mode 100644 index 000000000..6c2e4030e --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/EmployeeEntity.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.updatemethods; + +/** + * + * @author Sjaak Derksen + */ +public class EmployeeEntity { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousCompanyMapper1.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousCompanyMapper1.java index 375382a15..43a7651d9 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousCompanyMapper1.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousCompanyMapper1.java @@ -19,7 +19,9 @@ package org.mapstruct.ap.test.updatemethods; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** @@ -35,5 +37,9 @@ public interface ErroneousCompanyMapper1 { void toInBetween(DepartmentDto dto, @MappingTarget DepartmentInBetween entity); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) void toDepartmentEntity(DepartmentInBetween dto, @MappingTarget DepartmentEntity entity); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper1.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper1.java index cea30a75b..45df399b0 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper1.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper1.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.updatemethods; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** @@ -40,6 +41,10 @@ public interface ErroneousOrganizationMapper1 { @Mapping(source = "type", target = "type") void toName(String type, @MappingTarget OrganizationTypeEntity entity); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) DepartmentEntity toDepartmentEntity(DepartmentDto dto); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper2.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper2.java index b9d7cce7a..5213b6150 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper2.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/ErroneousOrganizationMapper2.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.test.updatemethods; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** @@ -40,6 +41,10 @@ public interface ErroneousOrganizationMapper2 { @Mapping(source = "type", target = "type") void toName(String type, @MappingTarget OrganizationTypeEntity entity); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) DepartmentEntity toDepartmentEntity(DepartmentDto dto); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/OrganizationMapper.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/OrganizationMapper.java index 3ea35e82c..a81aa185c 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/OrganizationMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/OrganizationMapper.java @@ -41,6 +41,10 @@ public interface OrganizationMapper { void toCompanyEntity(CompanyDto dto, @MappingTarget CompanyEntity entity); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) DepartmentEntity toDepartmentEntity(DepartmentDto dto); @Mapping(source = "type", target = "type") diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryDto.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryDto.java new file mode 100644 index 000000000..093d607de --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryDto.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.updatemethods; + +/** + * + * @author Sjaak Derksen + */ +public class SecretaryDto { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryEntity.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryEntity.java new file mode 100644 index 000000000..192e6032a --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/SecretaryEntity.java @@ -0,0 +1,37 @@ +/** + * Copyright 2012-2015 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.updatemethods; + +/** + * + * @author Sjaak Derksen + */ +public class SecretaryEntity { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/UpdateMethodsTest.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/UpdateMethodsTest.java index 68809ecaf..0c0bc5125 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/UpdateMethodsTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/UpdateMethodsTest.java @@ -36,20 +36,26 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; */ @IssueKey("160") @RunWith(AnnotationProcessorTestRunner.class) + @WithClasses({ + OrganizationDto.class, + OrganizationEntity.class, + CompanyDto.class, + CompanyEntity.class, + DepartmentDto.class, + DepartmentEntity.class, + DepartmentEntityFactory.class, + OrganizationTypeEntity.class, + OrganizationTypeNrEntity.class, + EmployeeDto.class, + EmployeeEntity.class, + SecretaryDto.class, + SecretaryEntity.class +}) public class UpdateMethodsTest { @Test @WithClasses( { - OrganizationMapper.class, - OrganizationDto.class, - OrganizationEntity.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class, - OrganizationTypeNrEntity.class + OrganizationMapper.class } ) public void testPreferUpdateMethod() { @@ -77,16 +83,7 @@ public class UpdateMethodsTest { @Test @WithClasses( { - OrganizationMapper.class, - OrganizationDto.class, - OrganizationEntity.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class, - OrganizationTypeNrEntity.class + OrganizationMapper.class } ) public void testPreferUpdateMethodSourceObjectNotDefined() { @@ -111,14 +108,7 @@ public class UpdateMethodsTest { @Test @WithClasses( { CompanyMapper.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentInBetween.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class, - OrganizationTypeNrEntity.class + DepartmentInBetween.class } ) public void testPreferUpdateMethodEncapsulatingCreateMethod() { @@ -138,21 +128,14 @@ public class UpdateMethodsTest { @Test @WithClasses( { ErroneousOrganizationMapper1.class, - OrganizationDto.class, - OrganizationWithoutCompanyGetterEntity.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class + OrganizationWithoutCompanyGetterEntity.class } ) @ExpectedCompilationOutcome( value = CompilationResult.FAILED, diagnostics = { @Diagnostic(type = ErroneousOrganizationMapper1.class, kind = javax.tools.Diagnostic.Kind.ERROR, - line = 36, + line = 37, messageRegExp = "No read accessor found for property \"company\" in target type.") } ) @@ -161,45 +144,30 @@ public class UpdateMethodsTest { @Test @WithClasses( { ErroneousOrganizationMapper2.class, - OrganizationDto.class, - OrganizationWithoutTypeGetterEntity.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class + OrganizationWithoutTypeGetterEntity.class } ) @ExpectedCompilationOutcome( value = CompilationResult.FAILED, diagnostics = { @Diagnostic(type = ErroneousOrganizationMapper2.class, kind = javax.tools.Diagnostic.Kind.ERROR, - line = 36, + line = 37, messageRegExp = "No read accessor found for property \"type\" in target type.") - } - ) + } ) public void testShouldFailOnConstantMappingNoPropertyGetter() { } @Test @WithClasses( { ErroneousCompanyMapper1.class, - OrganizationDto.class, - OrganizationWithoutTypeGetterEntity.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentInBetween.class, - DepartmentEntity.class, - DepartmentEntityFactory.class, - OrganizationTypeEntity.class + DepartmentInBetween.class + } ) @ExpectedCompilationOutcome( value = CompilationResult.FAILED, diagnostics = { @Diagnostic(type = ErroneousCompanyMapper1.class, kind = javax.tools.Diagnostic.Kind.ERROR, - line = 34, + line = 36, messageRegExp = "Can't map property \".*DepartmentDto department\" to \".*DepartmentEntity department.") } ) diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/DepartmentMapper.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/DepartmentMapper.java new file mode 100644 index 000000000..4b961da41 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/DepartmentMapper.java @@ -0,0 +1,46 @@ +/** + * Copyright 2012-2015 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.updatemethods.selection; + +import org.mapstruct.Mapper; +import org.mapstruct.MappingTarget; +import org.mapstruct.ap.test.updatemethods.DepartmentDto; +import org.mapstruct.ap.test.updatemethods.DepartmentEntity; +import org.mapstruct.ap.test.updatemethods.EmployeeDto; +import org.mapstruct.ap.test.updatemethods.EmployeeEntity; +import org.mapstruct.ap.test.updatemethods.SecretaryDto; +import org.mapstruct.ap.test.updatemethods.SecretaryEntity; +import org.mapstruct.factory.Mappers; + +/** + * + * @author Sjaak Derksen + */ +@Mapper( uses = ExternalHandWrittenMapper.class ) +public interface DepartmentMapper { + + DepartmentMapper INSTANCE = Mappers.getMapper( DepartmentMapper.class ); + + void toDepartmentEntity(DepartmentDto dto, @MappingTarget DepartmentEntity entity); + + EmployeeEntity toEmployeeEntity(EmployeeDto dto); + + SecretaryEntity toSecretaryEntity(SecretaryDto dto); + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalHandWrittenMapper.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalHandWrittenMapper.java index 44f38c561..fd2d5d06b 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalHandWrittenMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalHandWrittenMapper.java @@ -18,9 +18,15 @@ */ package org.mapstruct.ap.test.updatemethods.selection; +import java.util.List; +import java.util.Map; import org.mapstruct.MappingTarget; import org.mapstruct.ap.test.updatemethods.DepartmentDto; import org.mapstruct.ap.test.updatemethods.DepartmentEntity; +import org.mapstruct.ap.test.updatemethods.EmployeeDto; +import org.mapstruct.ap.test.updatemethods.EmployeeEntity; +import org.mapstruct.ap.test.updatemethods.SecretaryDto; +import org.mapstruct.ap.test.updatemethods.SecretaryEntity; /** * @@ -35,4 +41,24 @@ public class ExternalHandWrittenMapper { } } + public void toEmployeeEntityList(List dtos, @MappingTarget List entities) { + + if ( entities != null && dtos != null ) { + for ( EmployeeDto dto : dtos) { + entities.add( DepartmentMapper.INSTANCE.toEmployeeEntity( dto ) ); + } + } + + } + + public void toSecretaryEmployeeEntityMap(Map dtoMap, + @MappingTarget Map entityMap) { + + if ( entityMap != null && dtoMap != null ) { + for ( Map.Entry dtoEntry : dtoMap.entrySet() ) { + entityMap.put( DepartmentMapper.INSTANCE.toSecretaryEntity( dtoEntry.getKey() ) , + DepartmentMapper.INSTANCE.toEmployeeEntity( dtoEntry.getValue() ) ); + } + } + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalMapper.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalMapper.java index cc66dc96f..a800454f3 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalMapper.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalMapper.java @@ -19,7 +19,9 @@ package org.mapstruct.ap.test.updatemethods.selection; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; +import org.mapstruct.Mappings; import org.mapstruct.ap.test.updatemethods.DepartmentDto; import org.mapstruct.ap.test.updatemethods.DepartmentEntity; import org.mapstruct.factory.Mappers; @@ -33,6 +35,10 @@ public interface ExternalMapper { ExternalMapper INSTANCE = Mappers.getMapper( ExternalMapper.class ); + @Mappings({ + @Mapping( target = "employees", ignore = true ), + @Mapping( target = "secretaryToEmployee", ignore = true ) + }) void toDepartmentEntity(DepartmentDto dto, @MappingTarget DepartmentEntity entity); } diff --git a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalSelectionTest.java b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalSelectionTest.java index 089189b88..0661226d8 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalSelectionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/updatemethods/selection/ExternalSelectionTest.java @@ -18,6 +18,10 @@ */ package org.mapstruct.ap.test.updatemethods.selection; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import static org.fest.assertions.Assertions.assertThat; import org.junit.Test; import org.junit.runner.RunWith; import org.mapstruct.ap.test.updatemethods.CompanyDto; @@ -25,6 +29,10 @@ import org.mapstruct.ap.test.updatemethods.CompanyEntity; import org.mapstruct.ap.test.updatemethods.DepartmentDto; import org.mapstruct.ap.test.updatemethods.DepartmentEntity; import org.mapstruct.ap.test.updatemethods.DepartmentEntityFactory; +import org.mapstruct.ap.test.updatemethods.EmployeeDto; +import org.mapstruct.ap.test.updatemethods.EmployeeEntity; +import org.mapstruct.ap.test.updatemethods.SecretaryDto; +import org.mapstruct.ap.test.updatemethods.SecretaryEntity; import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; @@ -35,17 +43,26 @@ import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; */ @IssueKey("160") @RunWith(AnnotationProcessorTestRunner.class) +@WithClasses({ + OrganizationMapper1.class, + ExternalMapper.class, + ExternalHandWrittenMapper.class, + CompanyDto.class, + CompanyEntity.class, + DepartmentMapper.class, + DepartmentDto.class, + DepartmentEntityFactory.class, + DepartmentEntity.class, + EmployeeDto.class, + EmployeeEntity.class, + SecretaryDto.class, + SecretaryEntity.class +}) public class ExternalSelectionTest { @Test @WithClasses({ - OrganizationMapper1.class, - ExternalMapper.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntityFactory.class, - DepartmentEntity.class + OrganizationMapper1.class }) public void shouldSelectGeneratedExternalMapper() { @@ -56,13 +73,7 @@ public class ExternalSelectionTest { @Test @WithClasses({ - OrganizationMapper2.class, - ExternalHandWrittenMapper.class, - CompanyDto.class, - CompanyEntity.class, - DepartmentDto.class, - DepartmentEntityFactory.class, - DepartmentEntity.class + OrganizationMapper2.class }) public void shouldSelectGeneratedHandWrittenExternalMapper() { @@ -71,4 +82,33 @@ public class ExternalSelectionTest { OrganizationMapper2.INSTANCE.toCompanyEntity( dto, entity ); } + + @Test + @IssueKey( "487" ) + public void shouldSelectGeneratedExternalMapperForIterablesAndMaps() { + + DepartmentDto departmentDto = new DepartmentDto(); + EmployeeDto employeeDto = new EmployeeDto(); + employeeDto.setName( "Sarah" ); + SecretaryDto secretaryDto = new SecretaryDto(); + secretaryDto.setName( "Jim" ); + departmentDto.setEmployees( Arrays.asList( employeeDto ) ); + Map secretaryToEmployee = new HashMap(); + secretaryToEmployee.put( secretaryDto, employeeDto ); + departmentDto.setSecretaryToEmployee( secretaryToEmployee ); + + DepartmentEntity departmentEntity = new DepartmentEntity( 5 ); + + DepartmentMapper.INSTANCE.toDepartmentEntity( departmentDto, departmentEntity ); + + assertThat( departmentEntity ).isNotNull(); + assertThat( departmentEntity.getEmployees() ).isNotEmpty(); + assertThat( departmentEntity.getEmployees().get( 0 ).getName() ).isEqualTo( "Sarah" ); + assertThat( departmentEntity.getSecretaryToEmployee() ).isNotEmpty(); + Map.Entry firstEntry = + departmentEntity.getSecretaryToEmployee().entrySet().iterator().next(); + assertThat( firstEntry.getKey().getName() ).isEqualTo( "Jim" ); + assertThat( firstEntry.getValue().getName() ).isEqualTo( "Sarah" ); + + } }