mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#44 Enabling types with more than one type parameter
This commit is contained in:
parent
7d26a3b43e
commit
ac9859c38d
@ -83,7 +83,9 @@ public class Mapper extends AbstractModelElement {
|
||||
|
||||
addWithDependents( collection, typeToAdd.getCollectionImplementationType() );
|
||||
addWithDependents( collection, typeToAdd.getIterableImplementationType() );
|
||||
addWithDependents( collection, typeToAdd.getElementType() );
|
||||
for ( Type type : typeToAdd.getTypeParameters() ) {
|
||||
addWithDependents( collection, type );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,6 +21,7 @@ package org.mapstruct.ap.model;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -32,7 +33,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class Type implements Comparable<Type> {
|
||||
public class Type extends AbstractModelElement implements Comparable<Type> {
|
||||
|
||||
private static final Set<String> PRIMITIVE_TYPE_NAMES = new HashSet<String>(
|
||||
Arrays.asList( "boolean", "char", "byte", "short", "int", "long", "float", "double" )
|
||||
@ -54,7 +55,7 @@ public class Type implements Comparable<Type> {
|
||||
|
||||
private final String packageName;
|
||||
private final String name;
|
||||
private final Type elementType;
|
||||
private final List<Type> typeParameters;
|
||||
private final boolean isEnumType;
|
||||
private final boolean isCollectionType;
|
||||
private final boolean isIterableType;
|
||||
@ -68,10 +69,10 @@ public class Type implements Comparable<Type> {
|
||||
return new Type(
|
||||
pakkage.getName(),
|
||||
clazz.getSimpleName(),
|
||||
null,
|
||||
clazz.isEnum(),
|
||||
Collection.class.isAssignableFrom( clazz ),
|
||||
Iterable.class.isAssignableFrom( clazz )
|
||||
Iterable.class.isAssignableFrom( clazz ),
|
||||
Collections.<Type>emptyList()
|
||||
);
|
||||
}
|
||||
else {
|
||||
@ -80,21 +81,21 @@ public class Type implements Comparable<Type> {
|
||||
}
|
||||
|
||||
public Type(String name) {
|
||||
this( null, name, null, false, false, false );
|
||||
this( null, name, false, false, false, Collections.<Type>emptyList() );
|
||||
}
|
||||
|
||||
public Type(String packageName, String name) {
|
||||
this( packageName, name, null, false, false, false );
|
||||
this( packageName, name, false, false, false, Collections.<Type>emptyList() );
|
||||
}
|
||||
|
||||
public Type(String packageName, String name, Type elementType, boolean isEnumType, boolean isCollectionType,
|
||||
boolean isIterableType) {
|
||||
public Type(String packageName, String name, boolean isEnumType, boolean isCollectionType,
|
||||
boolean isIterableType, List<Type> typeParameters) {
|
||||
this.packageName = packageName;
|
||||
this.name = name;
|
||||
this.elementType = elementType;
|
||||
this.isEnumType = isEnumType;
|
||||
this.isCollectionType = isCollectionType;
|
||||
this.isIterableType = isIterableType;
|
||||
this.typeParameters = typeParameters;
|
||||
|
||||
if ( isCollectionType ) {
|
||||
collectionImplementationType = DEFAULT_COLLECTION_IMPLEMENTATION_TYPES.get( packageName + "." + name );
|
||||
@ -119,8 +120,8 @@ public class Type implements Comparable<Type> {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Type getElementType() {
|
||||
return elementType;
|
||||
public List<Type> getTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
@ -152,27 +153,17 @@ public class Type implements Comparable<Type> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if ( packageName == null ) {
|
||||
return name;
|
||||
}
|
||||
else if ( elementType == null ) {
|
||||
return packageName + "." + name;
|
||||
}
|
||||
else {
|
||||
return packageName + "." + name + "<" + elementType + ">";
|
||||
}
|
||||
public Set<Type> getImportTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ( ( elementType == null ) ? 0 : elementType.hashCode() );
|
||||
result = prime * result + ( ( name == null ) ? 0 : name.hashCode() );
|
||||
result = prime * result
|
||||
+ ( ( packageName == null ) ? 0 : packageName.hashCode() );
|
||||
result = prime * result + ( ( packageName == null ) ? 0 : packageName.hashCode() );
|
||||
result = prime * result + ( ( typeParameters == null ) ? 0 : typeParameters.hashCode() );
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -188,14 +179,6 @@ public class Type implements Comparable<Type> {
|
||||
return false;
|
||||
}
|
||||
Type other = (Type) obj;
|
||||
if ( elementType == null ) {
|
||||
if ( other.elementType != null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !elementType.equals( other.elementType ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( name == null ) {
|
||||
if ( other.name != null ) {
|
||||
return false;
|
||||
@ -212,6 +195,14 @@ public class Type implements Comparable<Type> {
|
||||
else if ( !packageName.equals( other.packageName ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( typeParameters == null ) {
|
||||
if ( other.typeParameters != null ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !typeParameters.equals( other.typeParameters ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -356,8 +356,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
private MappingMethod getIterableMappingMethod(List<Method> methods, Method method) {
|
||||
TypeConversion conversion = getIterableConversion(
|
||||
conversions,
|
||||
method.getSourceType().getElementType(),
|
||||
method.getTargetType().getElementType(),
|
||||
method.getSourceType().getTypeParameters().iterator().next(),
|
||||
method.getTargetType().getTypeParameters().iterator().next(),
|
||||
method.getIterableMapping()
|
||||
);
|
||||
|
||||
@ -368,8 +368,8 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
method.getTargetType(),
|
||||
getMappingMethodReference(
|
||||
methods,
|
||||
method.getSourceType().getElementType(),
|
||||
method.getTargetType().getElementType()
|
||||
method.getSourceType().getTypeParameters().iterator().next(),
|
||||
method.getTargetType().getTypeParameters().iterator().next()
|
||||
),
|
||||
conversion
|
||||
);
|
||||
@ -430,9 +430,9 @@ public class MapperCreationProcessor implements ModelElementProcessor<List<Metho
|
||||
Kind.ERROR,
|
||||
String.format(
|
||||
"Can't map property \"%s %s\" to \"%s %s\".",
|
||||
property.getSourceType(),
|
||||
property.getSourceType().getName(),
|
||||
property.getSourceName(),
|
||||
property.getTargetType(),
|
||||
property.getTargetType().getName(),
|
||||
property.getTargetName()
|
||||
),
|
||||
method.getExecutable()
|
||||
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
package org.mapstruct.ap.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
@ -43,20 +45,20 @@ public class TypeUtil {
|
||||
}
|
||||
|
||||
public Type getType(DeclaredType type) {
|
||||
Type elementType = null;
|
||||
List<Type> typeParameters = new ArrayList<Type>();
|
||||
|
||||
boolean isIterableType = isIterableType( type );
|
||||
if ( isIterableType && !type.getTypeArguments().isEmpty() ) {
|
||||
elementType = retrieveType( type.getTypeArguments().iterator().next() );
|
||||
for ( TypeMirror mirror : type.getTypeArguments() ) {
|
||||
typeParameters.add( retrieveType( mirror ) );
|
||||
}
|
||||
|
||||
return new Type(
|
||||
elementUtils.getPackageOf( type.asElement() ).toString(),
|
||||
type.asElement().getSimpleName().toString(),
|
||||
elementType,
|
||||
type.asElement().getKind() == ElementKind.ENUM,
|
||||
isCollectionType( type ),
|
||||
isIterableType
|
||||
isIterableType,
|
||||
typeParameters
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -19,15 +19,15 @@
|
||||
|
||||
-->
|
||||
@Override
|
||||
public ${targetType.name}<${targetType.elementType.name}> ${name}(${sourceType.name}<${sourceType.elementType.name}> ${parameterName}) {
|
||||
public <@includeModel object=targetType/> ${name}(<@includeModel object=sourceType/> ${parameterName}) {
|
||||
if ( ${parameterName} == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
<#-- 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 targetType.name == "Iterable" && targetType.packageName == "java.lang">${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><${targetType.elementType.name}> ${targetType.name?uncap_first} = new <#if targetType.iterableImplementationType??>${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><${targetType.elementType.name}>();
|
||||
<#if targetType.name == "Iterable" && targetType.packageName == "java.lang">${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><<@includeModel object=targetType.typeParameters[0]/>> ${targetType.name?uncap_first} = new <#if targetType.iterableImplementationType??>${targetType.iterableImplementationType.name}<#else>${targetType.name}</#if><<@includeModel object=targetType.typeParameters[0]/>>();
|
||||
|
||||
for ( ${sourceType.elementType.name} ${sourceType.elementType.name?uncap_first} : ${parameterName} ) {
|
||||
for ( <@includeModel object=sourceType.typeParameters[0]/> ${sourceType.typeParameters[0].name?uncap_first} : ${parameterName} ) {
|
||||
<#if conversion??>
|
||||
<#if (conversion.exceptionTypes?size == 0) >
|
||||
${targetType.name?uncap_first}.add( <@includeModel object=conversion/> );
|
||||
@ -42,7 +42,7 @@
|
||||
</#list>
|
||||
</#if>
|
||||
<#else>
|
||||
${targetType.name?uncap_first}.add( ${elementMappingMethod.name}( ${sourceType.elementType.name?uncap_first} ) );
|
||||
${targetType.name?uncap_first}.add( ${elementMappingMethod.name}( ${sourceType.typeParameters[0].name?uncap_first} ) );
|
||||
</#if>
|
||||
}
|
||||
|
||||
|
21
processor/src/main/resources/org.mapstruct.ap.model.Type.ftl
Normal file
21
processor/src/main/resources/org.mapstruct.ap.model.Type.ftl
Normal file
@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
Copyright 2012-2013 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.
|
||||
|
||||
-->
|
||||
${name}<#if (typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, </#if></#list>></#if>
|
Loading…
x
Reference in New Issue
Block a user