mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-26 00:00:05 +08:00
#611 Allow nested declaration of Mappers
* #611 Allow nested declaration of Mappers Up until now, if a Mapper was declared as a nested interface, say EnclosingClass.NestedMapper, the implementation of the mapper was generated as NestedMapperImpl in the same package. The Mappers factory class then tried to load EnclosingClass$NestedMapperImpl, which would fail.
This commit is contained in:
parent
3b9584ff13
commit
00385a1cdb
@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mapstruct.test.model.Foo;
|
import org.mapstruct.test.model.Foo;
|
||||||
|
import org.mapstruct.test.model.SomeClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for {@link Mappers}.
|
* Unit test for {@link Mappers}.
|
||||||
@ -36,4 +37,14 @@ public class MappersTest {
|
|||||||
Foo mapper = Mappers.getMapper( Foo.class );
|
Foo mapper = Mappers.getMapper( Foo.class );
|
||||||
assertThat( mapper ).isNotNull();
|
assertThat( mapper ).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an implementation of a nested mapper can be found. This is a special case since
|
||||||
|
* it is named
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void findsNestedMapperImpl() throws Exception {
|
||||||
|
assertThat( Mappers.getMapper( SomeClass.Foo.class ) ).isNotNull();
|
||||||
|
assertThat( Mappers.getMapper( SomeClass.NestedClass.Foo.class ) ).isNotNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.test.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For testing naming of implementations of nested mappers (issue 611).
|
||||||
|
*
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Turn off checkstyle since the underscore introduced by issue 611 violates the class naming
|
||||||
|
* convention.
|
||||||
|
*/
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
public class SomeClass$FooImpl implements SomeClass.Foo {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.test.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For testing naming of implementations of nested mappers (issue 611).
|
||||||
|
*
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Turn off checkstyle since the underscore introduced by issue 611 violates the class naming
|
||||||
|
* convention.
|
||||||
|
*/
|
||||||
|
// CHECKSTYLE:OFF
|
||||||
|
public class SomeClass$NestedClass$FooImpl implements SomeClass.NestedClass.Foo {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.test.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sole purpose of this class is to have a place to nest the Foo interface.
|
||||||
|
*
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
public class SomeClass {
|
||||||
|
public interface Foo { }
|
||||||
|
|
||||||
|
public static class NestedClass {
|
||||||
|
public interface Foo { }
|
||||||
|
}
|
||||||
|
}
|
@ -111,7 +111,7 @@ public class Decorator extends GeneratedType {
|
|||||||
|
|
||||||
public Decorator build() {
|
public Decorator build() {
|
||||||
String implementationName = implName.replace( Mapper.CLASS_NAME_PLACEHOLDER,
|
String implementationName = implName.replace( Mapper.CLASS_NAME_PLACEHOLDER,
|
||||||
mapperElement.getSimpleName() );
|
Mapper.getFlatName( mapperElement ) );
|
||||||
|
|
||||||
Type decoratorType = typeFactory.getType( decoratorPrism.value() );
|
Type decoratorType = typeFactory.getType( decoratorPrism.value() );
|
||||||
DecoratorConstructor decoratorConstructor = new DecoratorConstructor(
|
DecoratorConstructor decoratorConstructor = new DecoratorConstructor(
|
||||||
|
@ -21,6 +21,7 @@ package org.mapstruct.ap.internal.model;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
|
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ElementKind;
|
import javax.lang.model.element.ElementKind;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
import javax.lang.model.util.Elements;
|
import javax.lang.model.util.Elements;
|
||||||
@ -153,7 +154,7 @@ public class Mapper extends GeneratedType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Mapper build() {
|
public Mapper build() {
|
||||||
String implementationName = implName.replace( CLASS_NAME_PLACEHOLDER, element.getSimpleName() ) +
|
String implementationName = implName.replace( CLASS_NAME_PLACEHOLDER, getFlatName( element ) ) +
|
||||||
( decorator == null ? "" : "_" );
|
( decorator == null ? "" : "_" );
|
||||||
|
|
||||||
String elementPackage = elementUtils.getPackageOf( element ).getQualifiedName().toString();
|
String elementPackage = elementUtils.getPackageOf( element ).getQualifiedName().toString();
|
||||||
@ -199,4 +200,20 @@ public class Mapper extends GeneratedType {
|
|||||||
protected String getTemplateName() {
|
protected String getTemplateName() {
|
||||||
return getTemplateNameForClass( GeneratedType.class );
|
return getTemplateNameForClass( GeneratedType.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the same as {@link Class#getName()} but without the package declaration.
|
||||||
|
*/
|
||||||
|
public static String getFlatName(TypeElement element) {
|
||||||
|
if (!(element.getEnclosingElement() instanceof TypeElement)) {
|
||||||
|
return element.getSimpleName().toString();
|
||||||
|
}
|
||||||
|
StringBuilder nameBuilder = new StringBuilder( element.getSimpleName().toString() );
|
||||||
|
for (Element enclosing = element.getEnclosingElement(); enclosing instanceof TypeElement; enclosing =
|
||||||
|
enclosing.getEnclosingElement()) {
|
||||||
|
nameBuilder.insert( 0, '$' );
|
||||||
|
nameBuilder.insert( 0, enclosing.getSimpleName().toString() );
|
||||||
|
}
|
||||||
|
return nameBuilder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.bugs._611;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
@IssueKey("611")
|
||||||
|
@RunWith(AnnotationProcessorTestRunner.class)
|
||||||
|
@WithClasses({
|
||||||
|
SomeClass.class,
|
||||||
|
SomeOtherClass.class
|
||||||
|
})
|
||||||
|
public class Issue611Test {
|
||||||
|
/**
|
||||||
|
* Checks if an implementation of a nested mapper can be loaded at all.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void mapperIsFound() {
|
||||||
|
assertThat( SomeClass.InnerMapper.INSTANCE ).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an implementation of a nested mapper can be loaded which is nested into an already
|
||||||
|
* nested class.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void mapperNestedInsideNestedClassIsFound() {
|
||||||
|
assertThat( SomeClass.SomeInnerClass.InnerMapper.INSTANCE ).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if it is possible to load two mapper implementations which have equal simple names
|
||||||
|
* in the same package.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void rightMapperIsFound() {
|
||||||
|
SomeClass.InnerMapper.Source source1 = new SomeClass.InnerMapper.Source();
|
||||||
|
SomeOtherClass.InnerMapper.Source source2 = new SomeOtherClass.InnerMapper.Source();
|
||||||
|
|
||||||
|
SomeClass.InnerMapper.Target target1 = SomeClass.InnerMapper.INSTANCE.toTarget( source1 );
|
||||||
|
SomeOtherClass.InnerMapper.Target target2 = SomeOtherClass.InnerMapper.INSTANCE.toTarget( source2 );
|
||||||
|
|
||||||
|
assertThat( target1 ).isExactlyInstanceOf( SomeClass.InnerMapper.Target.class );
|
||||||
|
assertThat( target2 ).isExactlyInstanceOf( SomeOtherClass.InnerMapper.Target.class );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.bugs._611;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
public class SomeClass {
|
||||||
|
@Mapper
|
||||||
|
public interface InnerMapper {
|
||||||
|
InnerMapper INSTANCE = Mappers.getMapper( InnerMapper.class );
|
||||||
|
|
||||||
|
Target toTarget(Source in);
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SomeInnerClass {
|
||||||
|
@Mapper
|
||||||
|
public interface InnerMapper {
|
||||||
|
InnerMapper INSTANCE = Mappers.getMapper( InnerMapper.class );
|
||||||
|
|
||||||
|
Target toTarget(Source in);
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2017 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.bugs._611;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Tillmann Gaida
|
||||||
|
*/
|
||||||
|
public class SomeOtherClass {
|
||||||
|
@Mapper
|
||||||
|
public interface InnerMapper {
|
||||||
|
InnerMapper INSTANCE = Mappers.getMapper( InnerMapper.class );
|
||||||
|
|
||||||
|
Target toTarget(Source in);
|
||||||
|
|
||||||
|
class Source {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user