From aa06a767ac076a1d504a3b1555a73a7e61cea713 Mon Sep 17 00:00:00 2001 From: sjaakd Date: Sun, 2 Feb 2014 20:36:49 +0100 Subject: [PATCH] #81 adding implementation for Map and Iterable types, and adding unit test. NOTE a TODO is still in MapperCreationProcessor --- .../ap/model/IterableMappingMethod.java | 8 +++- .../mapstruct/ap/model/MapMappingMethod.java | 9 +++- .../ap/processor/MapperCreationProcessor.java | 41 +++++++++++-------- ...pstruct.ap.model.IterableMappingMethod.ftl | 2 +- ...rg.mapstruct.ap.model.MapMappingMethod.ftl | 2 +- .../ap/test/factories/CustomList.java | 30 ++++++++++++++ .../ap/test/factories/CustomListImpl.java | 39 ++++++++++++++++++ .../ap/test/factories/CustomMap.java | 30 ++++++++++++++ .../ap/test/factories/CustomMapImpl.java | 39 ++++++++++++++++++ .../ap/test/factories/FactoryTest.java | 19 ++++++++- .../mapstruct/ap/test/factories/Source.java | 22 ++++++++++ .../SourceTargetMapperAndBar2Factory.java | 14 +++++++ .../mapstruct/ap/test/factories/Target.java | 21 +++++++++- 13 files changed, 251 insertions(+), 25 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/factories/CustomList.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/factories/CustomListImpl.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/factories/CustomMap.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/factories/CustomMapImpl.java diff --git a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java index b263553f8..b4287f372 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/IterableMappingMethod.java @@ -36,12 +36,14 @@ public class IterableMappingMethod extends MappingMethod { private final MethodReference elementMappingMethod; private final TypeConversion conversion; + private final MethodReference factoryMethod; public IterableMappingMethod(Method method, MethodReference elementMappingMethod, - TypeConversion conversion) { + TypeConversion conversion, MethodReference factoryMethod) { super( method ); this.elementMappingMethod = elementMappingMethod; this.conversion = conversion; + this.factoryMethod = factoryMethod; } public Parameter getSourceParameter() { @@ -83,4 +85,8 @@ public class IterableMappingMethod extends MappingMethod { ), getParameterNames() ); } + + public MethodReference getFactoryMethod() { + return this.factoryMethod; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java index fe7260d54..7ef2ba64c 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MapMappingMethod.java @@ -37,15 +37,18 @@ public class MapMappingMethod extends MappingMethod { private final MethodReference valueMappingMethod; private final TypeConversion keyConversion; private final TypeConversion valueConversion; + private final MethodReference factoryMethod; public MapMappingMethod(Method method, MethodReference keyMappingMethod, TypeConversion keyConversion, - MethodReference valueMappingMethod, TypeConversion valueConversion) { + MethodReference valueMappingMethod, TypeConversion valueConversion, + MethodReference factoryMethod) { super( method ); this.keyMappingMethod = keyMappingMethod; this.keyConversion = keyConversion; this.valueMappingMethod = valueMappingMethod; this.valueConversion = valueConversion; + this.factoryMethod = factoryMethod; } public Parameter getSourceParameter() { @@ -108,4 +111,8 @@ public class MapMappingMethod extends MappingMethod { getParameterNames() ); } + + public MethodReference getFactoryMethod() { + return this.factoryMethod; + } } diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index 5aa8618fe..06a91927f 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -33,7 +33,6 @@ import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.ExecutableType; -import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.ElementFilter; import javax.lang.model.util.Elements; @@ -170,7 +169,8 @@ public class MapperCreationProcessor implements ModelElementProcessor> reverse(Map> mappings) { Map> reversed = new HashMap>(); @@ -608,10 +609,12 @@ public class MapperCreationProcessor implements ModelElementProcessor ${name}(<#list parameters as param><@i ${resultName}.clear(); <#else> <#-- Use the interface type on the left side, except it is java.lang.Iterable; use the implementation type - if present - on the right side --> - <#if resultType.fullyQualifiedName == "java.lang.Iterable"><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/> ${resultName} = new <#if resultType.implementationType??><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/>(); + <#if resultType.fullyQualifiedName == "java.lang.Iterable"><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod/><#else>new <#if resultType.implementationType??><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/>(); for ( <@includeModel object=sourceParameter.type.typeParameters[0]/> ${loopVariableName} : ${sourceParameter.name} ) { diff --git a/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl b/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl index 0f29df2b4..d4eadc94f 100644 --- a/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl +++ b/processor/src/main/resources/org.mapstruct.ap.model.MapMappingMethod.ftl @@ -27,7 +27,7 @@ public <@includeModel object=returnType /> ${name}(<#list parameters as param><@ <#if existingInstanceMapping> ${resultName}.clear(); <#else> - <@includeModel object=resultType /> ${resultName} = new <#if resultType.implementationType??><@includeModel object=resultType.implementationType /><#else><@includeModel object=resultType />(); + <@includeModel object=resultType /> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod/><#else>new <#if resultType.implementationType??><@includeModel object=resultType.implementationType /><#else><@includeModel object=resultType />(); for ( Map.Entry<<#list sourceParameter.type.typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, > ${entryVariableName} : ${sourceParameter.name}.entrySet() ) { diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/CustomList.java b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomList.java new file mode 100644 index 000000000..3232738d4 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomList.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.factories; + +import java.util.List; + +/** + * + * @author Sjaak Derksen + */ +public interface CustomList extends List { + + String getTypeProp(); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/CustomListImpl.java b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomListImpl.java new file mode 100644 index 000000000..fd9e2cbef --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomListImpl.java @@ -0,0 +1,39 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.factories; + +import java.util.LinkedList; + +/** + * + * @author Sjaak Derksen + */ +public class CustomListImpl extends LinkedList implements CustomList { + + private final String typeProp; + + public CustomListImpl( String typeProp ) { + this.typeProp = typeProp; + } + + @Override + public String getTypeProp() { + return typeProp; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMap.java b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMap.java new file mode 100644 index 000000000..c825bf623 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMap.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.factories; + +import java.util.Map; + +/** + * + * @author Sjaak Derksen + */ +public interface CustomMap extends Map { + + String getTypeProp(); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMapImpl.java b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMapImpl.java new file mode 100644 index 000000000..131121f4b --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/CustomMapImpl.java @@ -0,0 +1,39 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.test.factories; + +import java.util.HashMap; + +/** + * + * @author Sjaak Derksen + */ +public class CustomMapImpl extends HashMap implements CustomMap { + + private final String typeProp; + + public CustomMapImpl( String typeProp ) { + this.typeProp = typeProp; + } + + @Override + public String getTypeProp() { + return typeProp; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/FactoryTest.java b/processor/src/test/java/org/mapstruct/ap/test/factories/FactoryTest.java index cf9745c4c..063a72f61 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/factories/FactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/FactoryTest.java @@ -18,6 +18,10 @@ */ package org.mapstruct.ap.test.factories; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.mapstruct.ap.test.factories.a.BarFactory; import static org.fest.assertions.Assertions.assertThat; @@ -33,7 +37,7 @@ import org.testng.annotations.Test; @IssueKey( "81" ) @WithClasses( { Bar1.class, Foo1.class, Bar2.class, Foo2.class, Bar3.class, Foo3.class, BarFactory.class, org.mapstruct.ap.test.factories.b.BarFactory.class, Source.class, SourceTargetMapperAndBar2Factory.class, - Target.class } ) + Target.class, CustomList.class, CustomListImpl.class, CustomMap.class, CustomMapImpl.class } ) public class FactoryTest extends MapperTestBase { @Test public void shouldUseTwoFactoryMethods() { @@ -49,6 +53,12 @@ public class FactoryTest extends MapperTestBase { assertThat( target.getProp3() ).isNotNull(); assertThat( target.getProp3().getProp() ).isEqualTo( "foo3" ); assertThat( target.getProp3().getSomeTypeProp()).isEqualTo( "BAR3" ); + assertThat( target.getPropList() ).isNotNull(); + assertThat( target.getPropList().get( 0 ) ).isEqualTo( "fooListEntry" ); + assertThat( target.getPropList().getTypeProp()).isEqualTo( "CUSTOMLIST" ); + assertThat( target.getPropMap() ).isNotNull(); + assertThat( target.getPropMap().get( "key" ) ).isEqualTo( "fooValue" ); + assertThat( target.getPropMap().getTypeProp()).isEqualTo( "CUSTOMMAP" ); } private Source createSource() { @@ -66,6 +76,13 @@ public class FactoryTest extends MapperTestBase { foo3.setProp( "foo3" ); source.setProp3( foo3 ); + List fooList = new ArrayList(); + fooList.add( "fooListEntry" ); + source.setPropList( fooList ); + + Map fooMap = new HashMap(); + fooMap.put( "key", "fooValue"); + source.setPropMap( fooMap ); return source; } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/Source.java b/processor/src/test/java/org/mapstruct/ap/test/factories/Source.java index b276aa4c5..27e94cd74 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/factories/Source.java +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/Source.java @@ -18,6 +18,9 @@ */ package org.mapstruct.ap.test.factories; +import java.util.List; +import java.util.Map; + /** * @author Sjaak Derksen * @@ -27,6 +30,8 @@ public class Source { private Foo1 prop1; private Foo2 prop2; private Foo3 prop3; + private List propList; + private Map propMap; public Foo1 getProp1() { return prop1; @@ -51,4 +56,21 @@ public class Source { public void setProp3( Foo3 prop3 ) { this.prop3 = prop3; } + + public List getPropList() { + return propList; + } + + public void setPropList( List propList ) { + this.propList = propList; + } + + public Map getPropMap() { + return propMap; + } + + public void setPropMap( Map propMap ) { + this.propMap = propMap; + } + } diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/SourceTargetMapperAndBar2Factory.java b/processor/src/test/java/org/mapstruct/ap/test/factories/SourceTargetMapperAndBar2Factory.java index 1a496a40f..1a54bfef0 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/factories/SourceTargetMapperAndBar2Factory.java +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/SourceTargetMapperAndBar2Factory.java @@ -18,6 +18,8 @@ */ package org.mapstruct.ap.test.factories; +import java.util.List; +import java.util.Map; import org.mapstruct.ap.test.factories.a.BarFactory; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -39,7 +41,19 @@ public abstract class SourceTargetMapperAndBar2Factory { public abstract Bar3 foo3ToBar3(Foo3 foo3); + public abstract CustomList customListToList(List list); + + public abstract CustomMap customMapToMap(Map list); + public Bar2 createBar2() { return new Bar2("BAR2"); } + + public CustomList createCustomList() { + return new CustomListImpl("CUSTOMLIST"); + } + + public CustomMap createCustomMap() { + return new CustomMapImpl("CUSTOMMAP"); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/factories/Target.java b/processor/src/test/java/org/mapstruct/ap/test/factories/Target.java index 557c0b93a..8ab9696c6 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/factories/Target.java +++ b/processor/src/test/java/org/mapstruct/ap/test/factories/Target.java @@ -18,7 +18,6 @@ */ package org.mapstruct.ap.test.factories; - /** * @author Sjaak Derksen * @@ -28,7 +27,8 @@ public class Target { private Bar1 prop1; private Bar2 prop2; private Bar3 prop3; - + private CustomList propList; + private CustomMap propMap; public Bar1 getProp1() { return prop1; @@ -53,4 +53,21 @@ public class Target { public void setProp3( Bar3 prop3 ) { this.prop3 = prop3; } + + public CustomList getPropList() { + return propList; + } + + public void setPropList( CustomList propList ) { + this.propList = propList; + } + + public CustomMap getPropMap() { + return propMap; + } + + public void setPropMap( CustomMap propMap ) { + this.propMap = propMap; + } + }