#112 Making sure not more than one type with the same simple name is imported

This commit is contained in:
Gunnar Morling 2014-01-29 21:03:20 +01:00
parent 78b0943953
commit e5668325f0
24 changed files with 440 additions and 78 deletions

View File

@ -56,6 +56,9 @@
<property name="cacheFile" value="${checkstyle.cache.file}"/> <property name="cacheFile" value="${checkstyle.cache.file}"/>
<!-- Required for SuppressionCommentFilter -->
<module name="FileContentsHolder"/>
<!-- Checks for Javadoc comments. --> <!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html --> <!-- See http://checkstyle.sf.net/config_javadoc.html -->
<!-- <module name="JavadocMethod"/> --> <!-- <module name="JavadocMethod"/> -->
@ -183,4 +186,6 @@
</module> </module>
<module name="SuppressionCommentFilter"/>
</module> </module>

View File

@ -39,7 +39,6 @@ import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementKindVisitor6; import javax.lang.model.util.ElementKindVisitor6;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.Kind;
import org.mapstruct.Mapper;
import org.mapstruct.ap.option.Options; import org.mapstruct.ap.option.Options;
import org.mapstruct.ap.option.ReportingPolicy; import org.mapstruct.ap.option.ReportingPolicy;
import org.mapstruct.ap.processor.DefaultModelElementProcessorContext; import org.mapstruct.ap.processor.DefaultModelElementProcessorContext;
@ -122,7 +121,6 @@ public class MappingProcessor extends AbstractProcessor {
@Override @Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) { public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
for ( TypeElement annotation : annotations ) { for ( TypeElement annotation : annotations ) {
@ -134,6 +132,13 @@ public class MappingProcessor extends AbstractProcessor {
for ( Element mapperElement : roundEnvironment.getElementsAnnotatedWith( annotation ) ) { for ( Element mapperElement : roundEnvironment.getElementsAnnotatedWith( annotation ) ) {
TypeElement mapperTypeElement = asTypeElement( mapperElement ); TypeElement mapperTypeElement = asTypeElement( mapperElement );
// create a new context for each generated mapper in order to have imports of referenced types
// correctly managed;
// note that this assumes that a new source file is created for each mapper which must not
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
// of one outer interface
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
processMapperTypeElement( context, mapperTypeElement ); processMapperTypeElement( context, mapperTypeElement );
} }
} }

View File

@ -23,7 +23,6 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import javax.annotation.Generated; import javax.annotation.Generated;
import javax.lang.model.element.ElementKind; import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
@ -149,7 +148,8 @@ public class Mapper extends ModelElement {
return; return;
} }
if ( typeToAdd.getPackageName() != null && if ( typeToAdd.isImported() &&
typeToAdd.getPackageName() != null &&
!typeToAdd.getPackageName().equals( packageName ) && !typeToAdd.getPackageName().equals( packageName ) &&
!typeToAdd.getPackageName().startsWith( "java.lang" ) ) { !typeToAdd.getPackageName().startsWith( "java.lang" ) ) {
collection.add( typeToAdd ); collection.add( typeToAdd );

View File

@ -21,21 +21,16 @@ package org.mapstruct.ap.model.common;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Name; import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
/** /**
* Represents the type of a bean property, parameter etc. Each type corresponds to a {@link TypeMirror}, i.e. there are * Represents (a reference to) the type of a bean property, parameter etc. Types are managed per generated source file.
* different instances for e.g. {@code Set<String>} and {@code Set<Integer>}. * Each type corresponds to a {@link TypeMirror}, i.e. there are different instances for e.g. {@code Set<String>} and
* {@code Set<Integer>}.
* <p> * <p>
* Allows for a unified handling of declared and primitive types and usage within templates. Instances are obtained * Allows for a unified handling of declared and primitive types and usage within templates. Instances are obtained
* through {@link TypeFactory}. * through {@link TypeFactory}.
@ -44,58 +39,46 @@ import javax.lang.model.util.Types;
*/ */
public class Type extends ModelElement implements Comparable<Type> { public class Type extends ModelElement implements Comparable<Type> {
private final Types typeUtils;
private final TypeMirror typeMirror;
private final TypeElement typeElement;
private final List<Type> typeParameters;
private final Type implementationType;
private final String packageName; private final String packageName;
private final String name; private final String name;
private final String qualifiedName; private final String qualifiedName;
private final List<Type> typeParameters;
private final boolean isInterface; private final boolean isInterface;
private final boolean isEnumType; private final boolean isEnumType;
private final boolean isIterableType; private final boolean isIterableType;
private final boolean isCollectionType; private final boolean isCollectionType;
private final boolean isMapType; private final boolean isMapType;
private final Type implementationType; private final boolean isImported;
private final TypeMirror typeMirror;
private final Types typeUtils;
private final TypeElement typeElement;
public Type(TypeMirror typeMirror, List<Type> typeParameters, Type implementationType, boolean isIterableType, //CHECKSTYLE:OFF
boolean isCollectionType, boolean isMapType, Types typeUtils, public Type(Types typeUtils, TypeMirror typeMirror, TypeElement typeElement, List<Type> typeParameters,
Elements elementUtils) { Type implementationType, String packageName, String name, String qualifiedName, boolean isInterface,
boolean isEnumType, boolean isIterableType, boolean isCollectionType, boolean isMapType,
boolean isImported) {
this.typeUtils = typeUtils;
this.typeMirror = typeMirror; this.typeMirror = typeMirror;
this.implementationType = implementationType; this.typeElement = typeElement;
this.typeParameters = typeParameters; this.typeParameters = typeParameters;
this.implementationType = implementationType;
this.packageName = packageName;
this.name = name;
this.qualifiedName = qualifiedName;
this.isInterface = isInterface;
this.isEnumType = isEnumType;
this.isIterableType = isIterableType; this.isIterableType = isIterableType;
this.isCollectionType = isCollectionType; this.isCollectionType = isCollectionType;
this.isMapType = isMapType; this.isMapType = isMapType;
this.typeUtils = typeUtils; this.isImported = isImported;
DeclaredType declaredType = typeMirror.getKind() == TypeKind.DECLARED ? (DeclaredType) typeMirror : null;
if ( declaredType != null ) {
isEnumType = declaredType.asElement().getKind() == ElementKind.ENUM;
isInterface = declaredType.asElement().getKind() == ElementKind.INTERFACE;
name = declaredType.asElement().getSimpleName().toString();
typeElement = declaredType.asElement().accept( new TypeElementRetrievalVisitor(), null );
if ( typeElement != null ) {
packageName = elementUtils.getPackageOf( typeElement ).getQualifiedName().toString();
qualifiedName = typeElement.getQualifiedName().toString();
}
else {
packageName = null;
qualifiedName = name;
}
}
else {
isEnumType = false;
isInterface = false;
typeElement = null;
name = typeMirror.toString();
packageName = null;
qualifiedName = name;
}
} }
//CHECKSTYLE:ON
public TypeMirror getTypeMirror() { public TypeMirror getTypeMirror() {
return typeMirror; return typeMirror;
@ -159,8 +142,18 @@ public class Type extends ModelElement implements Comparable<Type> {
@Override @Override
public Set<Type> getImportTypes() { public Set<Type> getImportTypes() {
return implementationType != null ? org.mapstruct.ap.util.Collections.<Type>asSet( implementationType ) : return implementationType != null ? Collections.singleton( implementationType ) : Collections.<Type>emptySet();
Collections.<Type>emptySet(); }
/**
* Whether this type is imported by means of an import statement in the currently generated source file (meaning it
* can be referenced in the generated source using its simple name) or not (meaning it has to be referenced using
* the fully-qualified name).
*
* @return {@code true} if the type is imported, {@code false} otherwise.
*/
public boolean isImported() {
return isImported;
} }
/** /**
@ -266,11 +259,4 @@ public class Type extends ModelElement implements Comparable<Type> {
public String toString() { public String toString() {
return typeMirror.toString(); return typeMirror.toString();
} }
private static class TypeElementRetrievalVisitor extends SimpleElementVisitor6<TypeElement, Void> {
@Override
public TypeElement visitType(TypeElement e, Void p) {
return e;
}
}
} }

View File

@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentNavigableMap; import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListMap;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement; import javax.lang.model.element.VariableElement;
@ -42,6 +43,7 @@ import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements; import javax.lang.model.util.Elements;
import javax.lang.model.util.SimpleElementVisitor6;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
import org.mapstruct.ap.prism.MappingTargetPrism; import org.mapstruct.ap.prism.MappingTargetPrism;
@ -62,6 +64,7 @@ public class TypeFactory {
private final TypeMirror mapType; private final TypeMirror mapType;
private final Map<String, Type> implementationTypes = new HashMap<String, Type>(); private final Map<String, Type> implementationTypes = new HashMap<String, Type>();
private final Map<String, String> importedQualifiedTypesBySimpleName = new HashMap<String, String>();
public TypeFactory(Elements elementUtils, Types typeUtils) { public TypeFactory(Elements elementUtils, Types typeUtils) {
this.elementUtils = elementUtils; this.elementUtils = elementUtils;
@ -129,15 +132,55 @@ public class TypeFactory {
mapType mapType
); );
boolean isEnumType;
boolean isInterface;
String name;
String packageName;
TypeElement typeElement;
String qualifiedName;
DeclaredType declaredType = mirror.getKind() == TypeKind.DECLARED ? (DeclaredType) mirror : null;
if ( declaredType != null ) {
isEnumType = declaredType.asElement().getKind() == ElementKind.ENUM;
isInterface = declaredType.asElement().getKind() == ElementKind.INTERFACE;
name = declaredType.asElement().getSimpleName().toString();
typeElement = declaredType.asElement().accept( new TypeElementRetrievalVisitor(), null );
if ( typeElement != null ) {
packageName = elementUtils.getPackageOf( typeElement ).getQualifiedName().toString();
qualifiedName = typeElement.getQualifiedName().toString();
}
else {
packageName = null;
qualifiedName = name;
}
}
else {
isEnumType = false;
isInterface = false;
typeElement = null;
name = mirror.toString();
packageName = null;
qualifiedName = name;
}
return new Type( return new Type(
typeUtils,
mirror, mirror,
typeElement,
getTypeParameters( mirror ), getTypeParameters( mirror ),
implementationType, implementationType,
packageName,
name,
qualifiedName,
isInterface,
isEnumType,
isIterableType, isIterableType,
isCollectionType, isCollectionType,
isMapType, isMapType,
typeUtils, isImported( name, qualifiedName )
elementUtils
); );
} }
@ -221,20 +264,49 @@ public class TypeFactory {
if ( implementationType != null ) { if ( implementationType != null ) {
return new Type( return new Type(
typeUtils,
typeUtils.getDeclaredType( typeUtils.getDeclaredType(
implementationType.getTypeElement(), implementationType.getTypeElement(),
declaredType.getTypeArguments().toArray( new TypeMirror[] { } ) declaredType.getTypeArguments().toArray( new TypeMirror[] { } )
), ),
implementationType.getTypeElement(),
getTypeParameters( mirror ), getTypeParameters( mirror ),
null, null,
implementationType.getPackageName(),
implementationType.getName(),
implementationType.getFullyQualifiedName(),
implementationType.isInterface(),
implementationType.isEnumType(),
implementationType.isIterableType(), implementationType.isIterableType(),
implementationType.isCollectionType(), implementationType.isCollectionType(),
implementationType.isMapType(), implementationType.isMapType(),
typeUtils, isImported( implementationType.getName(), implementationType.getFullyQualifiedName() )
elementUtils
); );
} }
return null; return null;
} }
private boolean isImported(String name, String qualifiedName) {
String importedType = importedQualifiedTypesBySimpleName.get( name );
boolean imported = false;
if ( importedType != null ) {
if ( importedType.equals( qualifiedName ) ) {
imported = true;
}
}
else {
importedQualifiedTypesBySimpleName.put( name, qualifiedName );
imported = true;
}
return imported;
}
private static class TypeElementRetrievalVisitor extends SimpleElementVisitor6<TypeElement, Void> {
@Override
public TypeElement visitType(TypeElement e, Void p) {
return e;
}
}
} }

View File

@ -18,4 +18,4 @@
limitations under the License. limitations under the License.
--> -->
@${type.name} @<@includeModel object=type/>

View File

@ -18,5 +18,5 @@
limitations under the License. limitations under the License.
--> -->
<#nt><@includeModel object=annotation/> <#nt><@includeModel object=annotation/>
private ${mapperType.name} ${variableName}; private <@includeModel object=mapperType/> ${variableName};

View File

@ -19,13 +19,13 @@
--> -->
@Override @Override
public ${returnType.name} ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) { public <@includeModel object=returnType/> ${name}(<#list parameters as param><@includeModel object=param/><#if param_has_next>, </#if></#list>) {
if ( <#list sourceParameters as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && </#if></#list> ) { if ( <#list sourceParameters as sourceParam>${sourceParam.name} == null<#if sourceParam_has_next> && </#if></#list> ) {
return<#if returnType.name != "void"> null</#if>; return<#if returnType.name != "void"> null</#if>;
} }
<#if !existingInstanceMapping> <#if !existingInstanceMapping>
${resultType.name} ${resultName} = new ${resultType.name}(); <@includeModel object=resultType/> ${resultName} = new <@includeModel object=resultType/>();
</#if> </#if>
<#if (sourceParameters?size > 1)> <#if (sourceParameters?size > 1)>

View File

@ -18,4 +18,4 @@
limitations under the License. limitations under the License.
--> -->
private final ${mapperType.name} ${variableName} = <#if annotatedMapper>Mappers.getMapper( ${mapperType.name}.class );<#else>new ${mapperType.name}();</#if> private final <@includeModel object=mapperType/> ${variableName} = <#if annotatedMapper>Mappers.getMapper( <@includeModel object=mapperType/>.class );<#else>new <@includeModel object=mapperType/>();</#if>

View File

@ -34,12 +34,10 @@ import ${importedType.fullyQualifiedName};
public class ${implementationName} <#if superTypeInterface>implements<#else>extends</#if> ${interfaceName} { public class ${implementationName} <#if superTypeInterface>implements<#else>extends</#if> ${interfaceName} {
<#list referencedMappers as mapper> <#list referencedMappers as mapper>
<@includeModel object=mapper/> <#nt> <@includeModel object=mapper/>
</#list> </#list>
<#list mappingMethods as mappingMethod> <#list mappingMethods as mappingMethod>
<#nt> <@includeModel object=mappingMethod/>
<@includeModel object=mappingMethod/>
</#list> </#list>
} }

View File

@ -60,7 +60,7 @@ ${ext.targetBeanName}.${targetAccessorName}( ${sourceBeanName}.${sourceAccessorN
${targetBeanName}.${targetAccessorName}( <@includeModel object=conversion/> ); ${targetBeanName}.${targetAccessorName}( <@includeModel object=conversion/> );
} }
<#list conversion.exceptionTypes as exceptionType> <#list conversion.exceptionTypes as exceptionType>
catch( ${exceptionType.name} e ) { catch( <@includeModel object=exceptionType/> e ) {
throw new RuntimeException( e ); throw new RuntimeException( e );
} }
</#list> </#list>

View File

@ -18,4 +18,4 @@
limitations under the License. limitations under the License.
--> -->
${name}<#if (typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, </#if></#list>></#if> <#if imported>${name}<#else>${fullyQualifiedName}</#if><#if (typeParameters?size > 0) ><<#list typeParameters as typeParameter><@includeModel object=typeParameter /><#if typeParameter_has_next>, </#if></#list>></#if>

View File

@ -0,0 +1,47 @@
/**
* 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.imports;
import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.MapperTestBase;
import org.mapstruct.ap.testutil.WithClasses;
import org.testng.annotations.Test;
import static org.fest.assertions.Assertions.assertThat;
/**
* Test for generating a mapper which references types whose names clash with names of used annotations and exceptions.
*
* @author Gunnar Morling
*/
@IssueKey("112")
@WithClasses({ Named.class, ParseException.class, SourceTargetMapper.class, List.class, Map.class })
public class ConflictingTypesNamesTest extends MapperTestBase {
@Test
public void mapperImportingTypesWithConflictingNamesCanBeGenerated() {
Named source = new Named();
source.setFoo( 123 );
source.setBar( 456L );
ParseException target = SourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
}
}

View File

@ -0,0 +1,23 @@
/**
* 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.imports;
public class List {
}

View File

@ -0,0 +1,23 @@
/**
* 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.imports;
public class Map {
}

View File

@ -0,0 +1,50 @@
/**
* 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.imports;
public class Named {
private int foo;
private long bar;
private String qax;
public int getFoo() {
return foo;
}
public void setFoo(int foo) {
this.foo = foo;
}
public long getBar() {
return bar;
}
public void setBar(long bar) {
this.bar = bar;
}
public String getQax() {
return qax;
}
public void setQax(String qax) {
this.qax = qax;
}
}

View File

@ -0,0 +1,52 @@
/**
* 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.imports;
import java.util.Date;
public class ParseException {
private String foo;
private String bar;
private Date qax;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
public Date getQax() {
return qax;
}
public void setQax(Date qax) {
this.qax = qax;
}
}

View File

@ -0,0 +1,38 @@
/**
* 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.imports;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper(componentModel = "jsr330")
public interface SourceTargetMapper {
SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
ParseException sourceToTarget(Named source);
//custom types
Map listToMap(List list);
java.util.List<ParseException> namedsToExceptions(java.util.List<Named> source);
}

View File

@ -20,6 +20,8 @@ package org.mapstruct.ap.test.references.samename;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.references.samename.a.CustomMapper; import org.mapstruct.ap.test.references.samename.a.CustomMapper;
import org.mapstruct.ap.test.references.samename.model.Source;
import org.mapstruct.ap.test.references.samename.model.Target;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**

View File

@ -18,7 +18,10 @@
*/ */
package org.mapstruct.ap.test.references.samename; package org.mapstruct.ap.test.references.samename;
import org.mapstruct.ap.test.references.samename.a.AnotherSourceTargetMapper;
import org.mapstruct.ap.test.references.samename.a.CustomMapper; import org.mapstruct.ap.test.references.samename.a.CustomMapper;
import org.mapstruct.ap.test.references.samename.model.Source;
import org.mapstruct.ap.test.references.samename.model.Target;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.MapperTestBase; import org.mapstruct.ap.testutil.MapperTestBase;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
@ -33,8 +36,13 @@ import static org.fest.assertions.Assertions.assertThat;
*/ */
@IssueKey("112") @IssueKey("112")
@WithClasses({ @WithClasses({
Source.class, Target.class, SourceTargetMapper.class, CustomMapper.class, Source.class,
org.mapstruct.ap.test.references.samename.b.CustomMapper.class, Jsr330SourceTargetMapper.class Target.class,
SourceTargetMapper.class,
CustomMapper.class,
org.mapstruct.ap.test.references.samename.b.CustomMapper.class,
Jsr330SourceTargetMapper.class,
AnotherSourceTargetMapper.class
}) })
public class SeveralReferencedMappersWithSameSimpleNameTest extends MapperTestBase { public class SeveralReferencedMappersWithSameSimpleNameTest extends MapperTestBase {
@ -50,4 +58,17 @@ public class SeveralReferencedMappersWithSameSimpleNameTest extends MapperTestBa
assertThat( target.getFoo() ).isEqualTo( "246" ); assertThat( target.getFoo() ).isEqualTo( "246" );
assertThat( target.getBar() ).isEqualTo( "912" ); assertThat( target.getBar() ).isEqualTo( "912" );
} }
@Test
public void mapperInSamePackageAndAnotherMapperWithSameNameInAnotherPackageCanBeReferenced() {
Source source = new Source();
source.setFoo( 123 );
source.setBar( 456L );
Target target = AnotherSourceTargetMapper.INSTANCE.sourceToTarget( source );
assertThat( target ).isNotNull();
assertThat( target.getFoo() ).isEqualTo( "246" );
assertThat( target.getBar() ).isEqualTo( "912" );
}
} }

View File

@ -20,6 +20,8 @@ package org.mapstruct.ap.test.references.samename;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.references.samename.a.CustomMapper; import org.mapstruct.ap.test.references.samename.a.CustomMapper;
import org.mapstruct.ap.test.references.samename.model.Source;
import org.mapstruct.ap.test.references.samename.model.Target;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**

View File

@ -0,0 +1,38 @@
/**
* 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.references.samename.a;
import org.mapstruct.Mapper;
import org.mapstruct.ap.test.references.samename.model.Source;
import org.mapstruct.ap.test.references.samename.model.Target;
import org.mapstruct.factory.Mappers;
/**
* @author Gunnar Morling
*/
@Mapper(uses = {
CustomMapper.class,
org.mapstruct.ap.test.references.samename.b.CustomMapper.class
})
public interface AnotherSourceTargetMapper {
AnotherSourceTargetMapper INSTANCE = Mappers.getMapper( AnotherSourceTargetMapper.class );
Target sourceToTarget(Source source);
}

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.mapstruct.ap.test.references.samename; package org.mapstruct.ap.test.references.samename.model;
public class Source { public class Source {

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.mapstruct.ap.test.references.samename; package org.mapstruct.ap.test.references.samename.model;
public class Target { public class Target {