mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#81 adding implementation for Map and Iterable types, and adding unit test. NOTE a TODO is still in MapperCreationProcessor
This commit is contained in:
parent
3f94c51884
commit
aa06a767ac
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<List<Metho
|
||||
continue;
|
||||
}
|
||||
|
||||
reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType( method );
|
||||
// TODO: Either find a good check for this or remove?
|
||||
// reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType( method );
|
||||
|
||||
Method reverseMappingMethod = getReverseMappingMethod( methods, method );
|
||||
|
||||
@ -243,20 +243,21 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
return result;
|
||||
}
|
||||
|
||||
private void reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType(Method method) {
|
||||
if ( method.getReturnType().getTypeMirror().getKind() != TypeKind.VOID &&
|
||||
method.getReturnType().isInterface() &&
|
||||
method.getReturnType().getImplementationType() == null ) {
|
||||
messager.printMessage(
|
||||
Kind.ERROR,
|
||||
String.format(
|
||||
"No implementation type is registered for return type %s.",
|
||||
method.getReturnType()
|
||||
),
|
||||
method.getExecutable()
|
||||
);
|
||||
}
|
||||
}
|
||||
// TODO: Either find a good check for this or remove?
|
||||
// private void reportErrorIfNoImplementationTypeIsRegisteredForInterfaceReturnType(Method method) {
|
||||
// if ( method.getReturnType().getTypeMirror().getKind() != TypeKind.VOID &&
|
||||
// method.getReturnType().isInterface() &&
|
||||
// method.getReturnType().getImplementationType() == null ) {
|
||||
// messager.printMessage(
|
||||
// Kind.ERROR,
|
||||
// String.format(
|
||||
// "No implementation type is registered for return type %s.",
|
||||
// method.getReturnType()
|
||||
// ),
|
||||
// method.getExecutable()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
private Map<String, List<Mapping>> reverse(Map<String, List<Mapping>> mappings) {
|
||||
Map<String, List<Mapping>> reversed = new HashMap<String, List<Mapping>>();
|
||||
@ -608,10 +609,12 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
);
|
||||
}
|
||||
|
||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||
return new IterableMappingMethod(
|
||||
method,
|
||||
elementMappingMethod,
|
||||
conversion
|
||||
conversion,
|
||||
factoryMethod
|
||||
);
|
||||
}
|
||||
|
||||
@ -674,7 +677,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
);
|
||||
}
|
||||
|
||||
return new MapMappingMethod( method, keyMappingMethod, keyConversion, valueMappingMethod, valueConversion );
|
||||
MethodReference factoryMethod = getFactoryMethod( mapperReferences, methods, method.getReturnType() );
|
||||
return new MapMappingMethod( method, keyMappingMethod, keyConversion, valueMappingMethod, valueConversion,
|
||||
factoryMethod );
|
||||
}
|
||||
|
||||
private TypeConversion getConversion(Type sourceType, Type targetType, String dateFormat, String sourceReference) {
|
||||
|
@ -28,7 +28,7 @@ public <@includeModel object=returnType/> ${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/></#if> ${resultName} = new <#if resultType.implementationType??><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/></#if>();
|
||||
<#if resultType.fullyQualifiedName == "java.lang.Iterable"><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/></#if> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod/><#else>new <#if resultType.implementationType??><@includeModel object=resultType.implementationType/><#else><@includeModel object=resultType/></#if>()</#if>;
|
||||
</#if>
|
||||
|
||||
for ( <@includeModel object=sourceParameter.type.typeParameters[0]/> ${loopVariableName} : ${sourceParameter.name} ) {
|
||||
|
@ -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 /></#if>();
|
||||
<@includeModel object=resultType /> ${resultName} = <#if factoryMethod??><@includeModel object=factoryMethod/><#else>new <#if resultType.implementationType??><@includeModel object=resultType.implementationType /><#else><@includeModel object=resultType /></#if>()</#if>;
|
||||
</#if>
|
||||
|
||||
for ( Map.Entry<<#list sourceParameter.type.typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, </#if></#list>> ${entryVariableName} : ${sourceParameter.name}.entrySet() ) {
|
||||
|
@ -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<T> extends List<T> {
|
||||
|
||||
String getTypeProp();
|
||||
}
|
@ -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<T> extends LinkedList<T> implements CustomList<T> {
|
||||
|
||||
private final String typeProp;
|
||||
|
||||
public CustomListImpl( String typeProp ) {
|
||||
this.typeProp = typeProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeProp() {
|
||||
return typeProp;
|
||||
}
|
||||
}
|
@ -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<K, V> extends Map<K, V> {
|
||||
|
||||
String getTypeProp();
|
||||
}
|
@ -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<K, V> extends HashMap<K, V> implements CustomMap<K, V> {
|
||||
|
||||
private final String typeProp;
|
||||
|
||||
public CustomMapImpl( String typeProp ) {
|
||||
this.typeProp = typeProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeProp() {
|
||||
return typeProp;
|
||||
}
|
||||
}
|
@ -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<String> fooList = new ArrayList<String>();
|
||||
fooList.add( "fooListEntry" );
|
||||
source.setPropList( fooList );
|
||||
|
||||
Map<String, String> fooMap = new HashMap<String, String>();
|
||||
fooMap.put( "key", "fooValue");
|
||||
source.setPropMap( fooMap );
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
@ -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<String> propList;
|
||||
private Map<String, String> propMap;
|
||||
|
||||
public Foo1 getProp1() {
|
||||
return prop1;
|
||||
@ -51,4 +56,21 @@ public class Source {
|
||||
public void setProp3( Foo3 prop3 ) {
|
||||
this.prop3 = prop3;
|
||||
}
|
||||
|
||||
public List<String> getPropList() {
|
||||
return propList;
|
||||
}
|
||||
|
||||
public void setPropList( List<String> propList ) {
|
||||
this.propList = propList;
|
||||
}
|
||||
|
||||
public Map<String, String> getPropMap() {
|
||||
return propMap;
|
||||
}
|
||||
|
||||
public void setPropMap( Map<String, String> propMap ) {
|
||||
this.propMap = propMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<String> customListToList(List<String> list);
|
||||
|
||||
public abstract CustomMap<String, String> customMapToMap(Map<String, String> list);
|
||||
|
||||
public Bar2 createBar2() {
|
||||
return new Bar2("BAR2");
|
||||
}
|
||||
|
||||
public CustomList<String> createCustomList() {
|
||||
return new CustomListImpl<String>("CUSTOMLIST");
|
||||
}
|
||||
|
||||
public CustomMap<String, String> createCustomMap() {
|
||||
return new CustomMapImpl<String, String>("CUSTOMMAP");
|
||||
}
|
||||
}
|
||||
|
@ -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<String> propList;
|
||||
private CustomMap<String, String> propMap;
|
||||
|
||||
public Bar1 getProp1() {
|
||||
return prop1;
|
||||
@ -53,4 +53,21 @@ public class Target {
|
||||
public void setProp3( Bar3 prop3 ) {
|
||||
this.prop3 = prop3;
|
||||
}
|
||||
|
||||
public CustomList<String> getPropList() {
|
||||
return propList;
|
||||
}
|
||||
|
||||
public void setPropList( CustomList<String> propList ) {
|
||||
this.propList = propList;
|
||||
}
|
||||
|
||||
public CustomMap<String, String> getPropMap() {
|
||||
return propMap;
|
||||
}
|
||||
|
||||
public void setPropMap( CustomMap<String, String> propMap ) {
|
||||
this.propMap = propMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user