#1154 Add SPI for excluding types/elements from automatic sub-mapping generation

Default implementation of SPI ignores types in the java/javax packages
This commit is contained in:
Filip Hrisafov 2017-05-17 22:34:23 +02:00 committed by GitHub
parent 459354b6b8
commit 7cf77f4c26
30 changed files with 826 additions and 65 deletions

View File

@ -3,6 +3,8 @@
:toc: right :toc: right
:sectanchors: :sectanchors:
:Author: Gunnar Morling, Andreas Gudian, Sjaak Derksen, Filip Hrisafov and the MapStruct community :Author: Gunnar Morling, Andreas Gudian, Sjaak Derksen, Filip Hrisafov and the MapStruct community
:processor-dir: ../../../../processor
:processor-ap-test: {processor-dir}/src/test/java/org/mapstruct/ap/test
[[Preface]] [[Preface]]
== Preface == Preface
@ -815,7 +817,7 @@ When generating the implementation of a mapping method, MapStruct will apply the
* If source and target attribute have the same type, the value will be simply copied from source to target. If the attribute is a collection (e.g. a `List`) a copy of the collection will be set into the target attribute. * If source and target attribute have the same type, the value will be simply copied from source to target. If the attribute is a collection (e.g. a `List`) a copy of the collection will be set into the target attribute.
* If source and target attribute type differ, check whether there is a another mapping method which has the type of the source attribute as parameter type and the type of the target attribute as return type. If such a method exists it will be invoked in the generated mapping implementation. * If source and target attribute type differ, check whether there is a another mapping method which has the type of the source attribute as parameter type and the type of the target attribute as return type. If such a method exists it will be invoked in the generated mapping implementation.
* If no such method exists MapStruct will look whether a built-in conversion for the source and target type of the attribute exists. If this is the case, the generated mapping code will apply this conversion. * If no such method exists MapStruct will look whether a built-in conversion for the source and target type of the attribute exists. If this is the case, the generated mapping code will apply this conversion.
* If no such method was found MapStruct will try to generate an internal method that will do the mapping between the source and target attributes * If no such method was found MapStruct will try to generate an automatic sub-mapping method that will do the mapping between the source and target attributes
* If MapStruct could not create a name based mapping method an error will be raised at build time, indicating the non-mappable attribute and its path. * If MapStruct could not create a name based mapping method an error will be raised at build time, indicating the non-mappable attribute and its path.
include::controlling-nested-bean-mappings.asciidoc[] include::controlling-nested-bean-mappings.asciidoc[]
@ -2458,9 +2460,64 @@ public class CustomAccessorNamingStrategy extends DefaultAccessorNamingStrategy
==== ====
The `CustomAccessorNamingStrategy` makes use of the `DefaultAccessorNamingStrategy` (also available in mapstruct-processor) and relies on that class to leave most of the default behaviour unchanged. The `CustomAccessorNamingStrategy` makes use of the `DefaultAccessorNamingStrategy` (also available in mapstruct-processor) and relies on that class to leave most of the default behaviour unchanged.
To use a custom SPI implementation, it must be located in a seperate .jar file together with the file `META-INF/services/org.mapstruct.ap.spi.AccessorNamingStrategy` with the fully qualified name of your custom implementation as content (e.g. `org.mapstruct.example.CustomAccessorNamingStrategy`). This .jar file needs to be added to the annotation processor classpath (i.e. add it next to the place where you added the mapstruct-processor jar). To use a custom SPI implementation, it must be located in a separate JAR file together with the file `META-INF/services/org.mapstruct.ap.spi.AccessorNamingStrategy` with the fully qualified name of your custom implementation as content (e.g. `org.mapstruct.example.CustomAccessorNamingStrategy`). This JAR file needs to be added to the annotation processor classpath (i.e. add it next to the place where you added the mapstruct-processor jar).
[TIP] [TIP]
Fore more details: There's the above example is present in our our examples repository (https://github.com/mapstruct/mapstruct-examples). Fore more details: There's the above example is present in our our examples repository (https://github.com/mapstruct/mapstruct-examples).
[mapping-exclusion-provider]
=== Mapping Exclusion Provider
MapStruct offers the possibility to override the `MappingExclusionProvider` via the Service Provider Interface (SPI).
A nice example is to not allow MapStruct to create an automatic sub-mapping for a certain type,
i.e. MapStruct will not try to generate an automatic sub-mapping method for an excluded type.
[NOTE]
====
The `DefaultMappingExclusionProvider` will exclude all types under the `java` or `javax` packages.
This means that MapStruct will not try to generate an automatic sub-mapping method between some custom type and some type declared in the Java class library.
====
.Source object
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
include::{processor-ap-test}/nestedbeans/exclusions/custom/Source.java[tag=documentation]
----
====
.Target object
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
include::{processor-ap-test}/nestedbeans/exclusions/custom/Target.java[tag=documentation]
----
====
.Mapper definition
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
include::{processor-ap-test}/nestedbeans/exclusions/custom/ErroneousCustomExclusionMapper.java[tag=documentation]
----
====
We want to exclude the `NestedTarget` from the automatic sub-mapping method generation.
.CustomMappingExclusionProvider
====
[source, java, linenums]
[subs="verbatim,attributes"]
----
include::{processor-ap-test}/nestedbeans/exclusions/custom/CustomMappingExclusionProvider.java[tag=documentation]
----
====
To use a custom SPI implementation, it must be located in a separate JAR file
together with the file `META-INF/services/org.mapstruct.ap.spi.MappingExclusionProvider` with the fully qualified name of your custom implementation as content
(e.g. `org.mapstruct.example.CustomMappingExclusionProvider`).
This JAR file needs to be added to the annotation processor classpath
(i.e. add it next to the place where you added the mapstruct-processor jar).

View File

@ -50,7 +50,27 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
return myself; return myself;
} }
boolean isDisableSubMappingMethodsGeneration() { /**
* Checks if MapStruct is allowed to generate an automatic sub-mapping between {@code sourceType} and @{code
* targetType}.
* This will evaluate to {@code true}, when:
* <li>
* <ul>Automatic sub-mapping methods generation is not disabled</ul>
* <ul>MapStruct is allowed to generate an automatic sub-mapping between the {@code sourceType} and {@code
* targetType}</ul>
* </li>
*
* @param sourceType candidate source type to generate a sub-mapping from
* @param targetType candidate target type to generate a sub-mapping for
*
* @return {@code true} if MapStruct can try to generate an automatic sub-mapping between the types.
*/
boolean canGenerateAutoSubMappingBetween(Type sourceType, Type targetType) {
return !isDisableSubMappingMethodsGeneration() &&
ctx.canGenerateAutoSubMappingBetween( sourceType, targetType );
}
private boolean isDisableSubMappingMethodsGeneration() {
MapperConfiguration configuration = MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() ); MapperConfiguration configuration = MapperConfiguration.getInstanceOn( ctx.getMapperTypeElement() );
return configuration.isDisableSubMappingMethodsGeneration(); return configuration.isDisableSubMappingMethodsGeneration();
} }
@ -123,11 +143,11 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
* *
* @param method the method that should be mapped * @param method the method that should be mapped
* @param sourceErrorMessagePart the error message part for the source * @param sourceErrorMessagePart the error message part for the source
* @param sourceRHS the {@link SourceRHS} * @param sourceType the source type of the mapping
* @param targetType the type of the target mapping * @param targetType the type of the target mapping
* @param targetPropertyName the name of the target property * @param targetPropertyName the name of the target property
*/ */
void reportCannotCreateMapping(Method method, String sourceErrorMessagePart, SourceRHS sourceRHS, Type targetType, void reportCannotCreateMapping(Method method, String sourceErrorMessagePart, Type sourceType, Type targetType,
String targetPropertyName) { String targetPropertyName) {
ctx.getMessager().printMessage( ctx.getMessager().printMessage(
method.getExecutable(), method.getExecutable(),
@ -136,7 +156,7 @@ class AbstractBaseBuilder<B extends AbstractBaseBuilder<B>> {
targetType, targetType,
targetPropertyName, targetPropertyName,
targetType, targetType,
sourceRHS.getSourceType() /* original source type */ sourceType
); );
} }
} }

View File

@ -45,7 +45,7 @@ public abstract class AbstractMappingMethodBuilder<B extends AbstractMappingMeth
protected abstract boolean shouldUsePropertyNamesInHistory(); protected abstract boolean shouldUsePropertyNamesInHistory();
Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) { Assignment forgeMapping(SourceRHS sourceRHS, Type sourceType, Type targetType) {
if ( isDisableSubMappingMethodsGeneration() ) { if ( !canGenerateAutoSubMappingBetween( sourceType, targetType ) ) {
return null; return null;
} }

View File

@ -121,7 +121,7 @@ public abstract class ContainerMappingMethodBuilder<B extends ContainerMappingMe
reportCannotCreateMapping( reportCannotCreateMapping(
method, method,
String.format( "%s \"%s\"", sourceRHS.getSourceErrorMessagePart(), sourceRHS.getSourceType() ), String.format( "%s \"%s\"", sourceRHS.getSourceErrorMessagePart(), sourceRHS.getSourceType() ),
sourceRHS, sourceRHS.getSourceType(),
targetElementType, targetElementType,
"" ""
); );

View File

@ -0,0 +1,49 @@
/**
* 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.internal.model;
import java.util.regex.Pattern;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import org.mapstruct.ap.spi.MappingExclusionProvider;
/**
* The default implementation of the {@link MappingExclusionProvider} service provider interface.
*
* With the default implementation, MapStruct will not consider classes in the {@code java} and {@code javax} package
* as source / target for an automatic sub-mapping. The only exception is the {@link java.util.Collection},
* {@link java.util.Map} and {@link java.util.stream.Stream} types.
*
* @author Filip Hrisafov
* @since 1.2
*/
class DefaultMappingExclusionProvider implements MappingExclusionProvider {
private static final Pattern JAVA_JAVAX_PACKAGE = Pattern.compile( "^javax?\\..*" );
@Override
public boolean isExcluded(TypeElement typeElement) {
Name name = typeElement.getQualifiedName();
return name.length() != 0 && isFullyQualifiedNameExcluded( name );
}
protected boolean isFullyQualifiedNameExcluded(Name name) {
return JAVA_JAVAX_PACKAGE.matcher( name ).matches();
}
}

View File

@ -125,7 +125,7 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
keySourceRHS.getSourceErrorMessagePart(), keySourceRHS.getSourceErrorMessagePart(),
keySourceRHS.getSourceType() keySourceRHS.getSourceType()
), ),
keySourceRHS, keySourceRHS.getSourceType(),
keyTargetType, keyTargetType,
"" ""
); );
@ -175,7 +175,7 @@ public class MapMappingMethod extends NormalTypeMappingMethod {
valueSourceRHS.getSourceErrorMessagePart(), valueSourceRHS.getSourceErrorMessagePart(),
valueSourceRHS.getSourceType() valueSourceRHS.getSourceType()
), ),
valueSourceRHS, valueSourceRHS.getSourceType(),
valueTargetType, valueTargetType,
"" ""
); );

View File

@ -29,15 +29,17 @@ import javax.lang.model.util.Elements;
import javax.lang.model.util.Types; import javax.lang.model.util.Types;
import org.mapstruct.ap.internal.model.assignment.Assignment; import org.mapstruct.ap.internal.model.assignment.Assignment;
import org.mapstruct.ap.internal.model.common.FormattingParameters;
import org.mapstruct.ap.internal.model.common.Type; import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory; import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.model.source.ForgedMethod; import org.mapstruct.ap.internal.model.source.ForgedMethod;
import org.mapstruct.ap.internal.model.common.FormattingParameters;
import org.mapstruct.ap.internal.model.source.Method; import org.mapstruct.ap.internal.model.source.Method;
import org.mapstruct.ap.internal.model.source.SelectionParameters; import org.mapstruct.ap.internal.model.source.SelectionParameters;
import org.mapstruct.ap.internal.model.source.SourceMethod; import org.mapstruct.ap.internal.model.source.SourceMethod;
import org.mapstruct.ap.internal.option.Options; import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.util.FormattingMessager; import org.mapstruct.ap.internal.util.FormattingMessager;
import org.mapstruct.ap.internal.util.Services;
import org.mapstruct.ap.spi.MappingExclusionProvider;
/** /**
* This class provides the context for the builders. * This class provides the context for the builders.
@ -54,6 +56,11 @@ import org.mapstruct.ap.internal.util.FormattingMessager;
*/ */
public class MappingBuilderContext { public class MappingBuilderContext {
private static final MappingExclusionProvider SUB_MAPPING_EXCLUSION_PROVIDER = Services.get(
MappingExclusionProvider.class,
new DefaultMappingExclusionProvider()
);
/** /**
* Resolves the most suitable way for mapping an element (property, iterable element etc.) from source to target. * Resolves the most suitable way for mapping an element (property, iterable element etc.) from source to target.
* There are 2 basic types of mappings: * There are 2 basic types of mappings:
@ -222,4 +229,23 @@ public class MappingBuilderContext {
return mappingResolver.getUsedVirtualMappings(); return mappingResolver.getUsedVirtualMappings();
} }
/**
* @param sourceType from which an automatic sub-mapping needs to be generated
* @param targetType to which an automatic sub-mapping needs to be generated
*
* @return {@code true} if MapStruct is allowed to try and generate an automatic sub-mapping between the
* source and target {@link Type}
*/
public boolean canGenerateAutoSubMappingBetween(Type sourceType, Type targetType) {
return canGenerateAutoSubMappingFor( sourceType ) && canGenerateAutoSubMappingFor( targetType );
}
/**
* @param type that MapStruct wants to use to genrate an autoamtic sub-mapping for/from
*
* @return {@code true} if the type is not excluded from the {@link MappingExclusionProvider}
*/
private boolean canGenerateAutoSubMappingFor(Type type) {
return type.getTypeElement() != null && !SUB_MAPPING_EXCLUSION_PROVIDER.isExcluded( type.getTypeElement() );
}
} }

View File

@ -304,13 +304,7 @@ public class PropertyMapping extends ModelElement {
} }
} }
else { else {
reportCannotCreateMapping( reportCannotCreateMapping();
method,
rightHandSide.getSourceErrorMessagePart(),
rightHandSide,
targetType,
targetPropertyName
);
} }
return new PropertyMapping( return new PropertyMapping(
@ -325,6 +319,31 @@ public class PropertyMapping extends ModelElement {
); );
} }
/**
* Report that a mapping could not be created.
*/
private void reportCannotCreateMapping() {
if ( method instanceof ForgedMethod && ( (ForgedMethod) method ).getHistory() != null ) {
ForgedMethodHistory history = ( (ForgedMethod) method ).getHistory();
reportCannotCreateMapping(
method,
history.createSourcePropertyErrorMessage(),
history.getSourceType(),
history.getTargetType(),
history.createTargetPropertyName()
);
}
else {
reportCannotCreateMapping(
method,
rightHandSide.getSourceErrorMessagePart(),
rightHandSide.getSourceType(),
targetType,
targetPropertyName
);
}
}
private Assignment getDefaultValueAssignment( Assignment rhs ) { private Assignment getDefaultValueAssignment( Assignment rhs ) {
if ( defaultValue != null if ( defaultValue != null
&& ( !rhs.getSourceType().isPrimitive() || rhs.getSourcePresenceCheckerReference() != null) ) { && ( !rhs.getSourceType().isPrimitive() || rhs.getSourcePresenceCheckerReference() != null) ) {
@ -582,11 +601,11 @@ public class PropertyMapping extends ModelElement {
} }
private Assignment forgeMapping(SourceRHS sourceRHS) { private Assignment forgeMapping(SourceRHS sourceRHS) {
if ( forgedNamedBased && isDisableSubMappingMethodsGeneration() ) { Type sourceType = sourceRHS.getSourceType();
if ( forgedNamedBased && !canGenerateAutoSubMappingBetween( sourceType, targetType ) ) {
return null; return null;
} }
Type sourceType = sourceRHS.getSourceType();
//Fail fast. If we could not find the method by now, no need to try //Fail fast. If we could not find the method by now, no need to try
if ( sourceType.isPrimitive() || targetType.isPrimitive() ) { if ( sourceType.isPrimitive() || targetType.isPrimitive() ) {

View File

@ -0,0 +1,66 @@
/**
* 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.spi;
import javax.lang.model.element.TypeElement;
import org.mapstruct.util.Experimental;
/**
* A service provider interface that is used to control if MapStruct is allowed to generate automatic sub-mapping for
* a given {@link TypeElement}.
*
* When generating the implementation of a mapping method, MapStruct will apply the following routine for each
* attribute pair in the source and target object:
*
* <ul>
* <li>If source and target attribute have the same type, the value will be simply copied from source to target.
* If the attribute is a collection (e.g. a `List`) a copy of the collection will be set into the target
* attribute.</li>
* <li>If source and target attribute type differ, check whether there is a another mapping method which has the
* type of the source attribute as parameter type and the type of the target attribute as return type. If such a
* method exists it will be invoked in the generated mapping implementation.</li>
* <li>If no such method exists MapStruct will look whether a built-in conversion for the source and target type
* of the attribute exists. If this is the case, the generated mapping code will apply this conversion.</li>
* <li>If no such method was found MapStruct will try to generate an automatic sub-mapping method that will do
* the mapping between the source and target attributes</li>
* <li>If MapStruct could not create a name based mapping method an error will be raised at build time,
* indicating the non-mappable attribute and its path.</li>
* </ul>
*
* With this SPI the last step before raising an error can be controlled. i.e. A user can control whether MapStruct
* is allowed to generate such automatic sub-mapping method (for the source or target type) or not.
*
* @author Filip Hrisafov
* @since 1.2
*/
@Experimental("This SPI can have it's signature changed in subsequent releases")
public interface MappingExclusionProvider {
/**
* Checks if MapStruct should not generate an automatic sub-mapping for the provided {@link TypeElement}, i.e.
* MapStruct will not try to descent into this class and won't try to automatically map it with some other type.
* The given {@code typeElement} will be excluded from the automatic sub-mapping generation
*
* @param typeElement that needs to be checked
*
* @return {@code true} if MapStruct should exclude the provided {@link TypeElement} from an automatic sub-mapping
*/
boolean isExcluded(TypeElement typeElement);
}

View File

@ -0,0 +1,25 @@
/**
* 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;
/**
* @author Filip Hrisafov
*/
public class NoProperties {
}

View File

@ -0,0 +1,35 @@
/**
* 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;
/**
* @author Filip Hrisafov
*/
public class WithProperties {
private String string;
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}

View File

@ -22,6 +22,8 @@ import javax.tools.Diagnostic.Kind;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
@ -108,16 +110,16 @@ public class ErroneousCollectionMappingTest {
@Test @Test
@IssueKey("459") @IssueKey("459")
@WithClasses({ ErroneousCollectionNoElementMappingFound.class }) @WithClasses({ ErroneousCollectionNoElementMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousCollectionNoElementMappingFound.class, @Diagnostic(type = ErroneousCollectionNoElementMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 37, line = 38,
messageRegExp = messageRegExp = "Can't map Collection element \".*WithProperties withProperties\" to \".*NoProperties" +
"Can't map Collection element \".*AttributedString attributedString\" to \".*String string\". " + " noProperties\". Consider to declare/implement a mapping method: \".*NoProperties map\\(" +
"Consider to declare/implement a mapping method: \".*String map(.*AttributedString value)") ".*WithProperties value\\)")
} }
) )
public void shouldFailOnNoElementMappingFound() { public void shouldFailOnNoElementMappingFound() {
@ -142,15 +144,16 @@ public class ErroneousCollectionMappingTest {
@Test @Test
@IssueKey("459") @IssueKey("459")
@WithClasses({ ErroneousCollectionNoKeyMappingFound.class }) @WithClasses({ ErroneousCollectionNoKeyMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousCollectionNoKeyMappingFound.class, @Diagnostic(type = ErroneousCollectionNoKeyMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 37, line = 38,
messageRegExp = "Can't map Map key \".*AttributedString attributedString\" to \".*String string\". " + messageRegExp = "Can't map Map key \".*WithProperties withProperties\" to \".*NoProperties " +
"Consider to declare/implement a mapping method: \".*String map(.*AttributedString value)") "noProperties\". Consider to declare/implement a mapping method: \".*NoProperties map\\(" +
".*WithProperties value\\)")
} }
) )
public void shouldFailOnNoKeyMappingFound() { public void shouldFailOnNoKeyMappingFound() {
@ -174,15 +177,16 @@ public class ErroneousCollectionMappingTest {
@Test @Test
@IssueKey("459") @IssueKey("459")
@WithClasses({ ErroneousCollectionNoValueMappingFound.class }) @WithClasses({ ErroneousCollectionNoValueMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousCollectionNoValueMappingFound.class, @Diagnostic(type = ErroneousCollectionNoValueMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 37, line = 38,
messageRegExp = "Can't map Map value \".*AttributedString attributedString\" to \".*String string\". " + messageRegExp = "Can't map Map value \".*WithProperties withProperties\" to \".*NoProperties " +
"Consider to declare/implement a mapping method: \".*String map(.*AttributedString value)") "noProperties\". Consider to declare/implement a mapping method: \".*NoProperties map\\(" +
".*WithProperties value\\)")
} }
) )
public void shouldFailOnNoValueMappingFound() { public void shouldFailOnNoValueMappingFound() {

View File

@ -18,10 +18,11 @@
*/ */
package org.mapstruct.ap.test.collection.erroneous; package org.mapstruct.ap.test.collection.erroneous;
import java.text.AttributedString;
import java.util.List; import java.util.List;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -34,6 +35,6 @@ public interface ErroneousCollectionNoElementMappingFound {
ErroneousCollectionNoElementMappingFound INSTANCE = ErroneousCollectionNoElementMappingFound INSTANCE =
Mappers.getMapper( ErroneousCollectionNoElementMappingFound.class ); Mappers.getMapper( ErroneousCollectionNoElementMappingFound.class );
List<String> map(List<AttributedString> source); List<NoProperties> map(List<WithProperties> source);
} }

View File

@ -18,10 +18,11 @@
*/ */
package org.mapstruct.ap.test.collection.erroneous; package org.mapstruct.ap.test.collection.erroneous;
import java.text.AttributedString;
import java.util.Map; import java.util.Map;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -34,6 +35,6 @@ public interface ErroneousCollectionNoKeyMappingFound {
ErroneousCollectionNoKeyMappingFound INSTANCE = ErroneousCollectionNoKeyMappingFound INSTANCE =
Mappers.getMapper( ErroneousCollectionNoKeyMappingFound.class ); Mappers.getMapper( ErroneousCollectionNoKeyMappingFound.class );
Map<String, String> map(Map<AttributedString, String> source); Map<NoProperties, String> map(Map<WithProperties, String> source);
} }

View File

@ -18,10 +18,11 @@
*/ */
package org.mapstruct.ap.test.collection.erroneous; package org.mapstruct.ap.test.collection.erroneous;
import java.text.AttributedString;
import java.util.Map; import java.util.Map;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -34,6 +35,6 @@ public interface ErroneousCollectionNoValueMappingFound {
ErroneousCollectionNoValueMappingFound INSTANCE = ErroneousCollectionNoValueMappingFound INSTANCE =
Mappers.getMapper( ErroneousCollectionNoValueMappingFound.class ); Mappers.getMapper( ErroneousCollectionNoValueMappingFound.class );
Map<String, String> map(Map<String, AttributedString> source); Map<String, NoProperties> map(Map<String, WithProperties> source);
} }

View File

@ -18,11 +18,12 @@
*/ */
package org.mapstruct.ap.test.java8stream.erroneous; package org.mapstruct.ap.test.java8stream.erroneous;
import java.text.AttributedString;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -34,5 +35,5 @@ public interface ErroneousListToStreamNoElementMappingFound {
ErroneousListToStreamNoElementMappingFound INSTANCE = ErroneousListToStreamNoElementMappingFound INSTANCE =
Mappers.getMapper( ErroneousListToStreamNoElementMappingFound.class ); Mappers.getMapper( ErroneousListToStreamNoElementMappingFound.class );
Stream<String> mapCollectionToStream(List<AttributedString> source); Stream<NoProperties> mapCollectionToStream(List<WithProperties> source);
} }

View File

@ -22,6 +22,8 @@ import javax.tools.Diagnostic.Kind;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
@ -108,16 +110,16 @@ public class ErroneousStreamMappingTest {
} }
@Test @Test
@WithClasses({ ErroneousStreamToStreamNoElementMappingFound.class }) @WithClasses({ ErroneousStreamToStreamNoElementMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousStreamToStreamNoElementMappingFound.class, @Diagnostic(type = ErroneousStreamToStreamNoElementMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 36, line = 37,
messageRegExp = "Can't map Stream element \".*AttributedString attributedString\" to \".*String " + messageRegExp = "Can't map Stream element \".*WithProperties withProperties\" to \".*NoProperties " +
"string\". Consider to declare/implement a mapping method: \".*String map(.*AttributedString " + "noProperties\". Consider to declare/implement a mapping method: \".*NoProperties map\\(" +
"value)") ".*WithProperties value\\)")
} }
) )
public void shouldFailOnNoElementMappingFoundForStreamToStream() { public void shouldFailOnNoElementMappingFoundForStreamToStream() {
@ -140,16 +142,17 @@ public class ErroneousStreamMappingTest {
} }
@Test @Test
@WithClasses({ ErroneousListToStreamNoElementMappingFound.class }) @WithClasses({ ErroneousListToStreamNoElementMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousListToStreamNoElementMappingFound.class, @Diagnostic(type = ErroneousListToStreamNoElementMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 37, line = 38,
messageRegExp = messageRegExp =
"Can't map Stream element \".*AttributedString attributedString\" to \".*String string\". " + "Can't map Stream element \".*WithProperties withProperties\" to \".*NoProperties noProperties\"." +
"Consider to declare/implement a mapping method: \".*String map\\(.*AttributedString value\\)") " Consider to declare/implement a mapping method: \".*NoProperties map\\(.*WithProperties " +
"value\\)")
} }
) )
public void shouldFailOnNoElementMappingFoundForListToStream() { public void shouldFailOnNoElementMappingFoundForListToStream() {
@ -172,16 +175,16 @@ public class ErroneousStreamMappingTest {
} }
@Test @Test
@WithClasses({ ErroneousStreamToListNoElementMappingFound.class }) @WithClasses({ ErroneousStreamToListNoElementMappingFound.class, NoProperties.class, WithProperties.class })
@ExpectedCompilationOutcome( @ExpectedCompilationOutcome(
value = CompilationResult.FAILED, value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousStreamToListNoElementMappingFound.class, @Diagnostic(type = ErroneousStreamToListNoElementMappingFound.class,
kind = Kind.ERROR, kind = Kind.ERROR,
line = 37, line = 38,
messageRegExp = messageRegExp =
"Can't map Stream element \".*AttributedString attributedString\" to .*String string\"." + "Can't map Stream element \".*WithProperties withProperties\" to .*NoProperties noProperties\"." +
" Consider to declare/implement a mapping method: \".*String map(.*AttributedString value)") " Consider to declare/implement a mapping method: \".*NoProperties map(.*WithProperties value)")
} }
) )
public void shouldFailOnNoElementMappingFoundForStreamToList() { public void shouldFailOnNoElementMappingFoundForStreamToList() {

View File

@ -18,11 +18,12 @@
*/ */
package org.mapstruct.ap.test.java8stream.erroneous; package org.mapstruct.ap.test.java8stream.erroneous;
import java.text.AttributedString;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -34,5 +35,5 @@ public interface ErroneousStreamToListNoElementMappingFound {
ErroneousStreamToListNoElementMappingFound INSTANCE = ErroneousStreamToListNoElementMappingFound INSTANCE =
Mappers.getMapper( ErroneousStreamToListNoElementMappingFound.class ); Mappers.getMapper( ErroneousStreamToListNoElementMappingFound.class );
List<String> mapStreamToCollection(Stream<AttributedString> source); List<NoProperties> mapStreamToCollection(Stream<WithProperties> source);
} }

View File

@ -18,10 +18,11 @@
*/ */
package org.mapstruct.ap.test.java8stream.erroneous; package org.mapstruct.ap.test.java8stream.erroneous;
import java.text.AttributedString;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.test.WithProperties;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
/** /**
@ -33,5 +34,5 @@ public interface ErroneousStreamToStreamNoElementMappingFound {
ErroneousStreamToStreamNoElementMappingFound INSTANCE = ErroneousStreamToStreamNoElementMappingFound INSTANCE =
Mappers.getMapper( ErroneousStreamToStreamNoElementMappingFound.class ); Mappers.getMapper( ErroneousStreamToStreamNoElementMappingFound.class );
Stream<String> mapStreamToStream(Stream<AttributedString> source); Stream<NoProperties> mapStreamToStream(Stream<WithProperties> source);
} }

View File

@ -0,0 +1,30 @@
/**
* 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.nestedbeans.exclusions;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
@Mapper
public interface ErroneousJavaInternalMapper {
Target map(Source entity);
}

View File

@ -0,0 +1,65 @@
/**
* 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.nestedbeans.exclusions;
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.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
/**
* @author Filip Hrisafov
*/
@WithClasses({
Source.class,
Target.class,
ErroneousJavaInternalMapper.class
})
@RunWith(AnnotationProcessorTestRunner.class)
@IssueKey("1154")
public class ErroneousJavaInternalTest {
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousJavaInternalMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 29,
messageRegExp = "Can't map property \".*MyType date\" to \"java\\.util\\.Date date\"\\. Consider to " +
"declare/implement a mapping method: \"java\\.util\\.Date map\\(.*MyType value\\)\"\\."),
@Diagnostic(type = ErroneousJavaInternalMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 29,
messageRegExp = "Can't map property \".*MyType calendar\" to \"java\\.util\\.GregorianCalendar " +
"calendar\"\\. Consider to declare/implement a mapping method: \"java\\.util\\.GregorianCalendar " +
"map\\(.*MyType value\\)\"\\."),
@Diagnostic(type = ErroneousJavaInternalMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 29,
messageRegExp = "Can't map property \".*List<.*MyType> types\" to \".*List<.*String> types\"\\" +
". Consider to declare/implement a mapping method: \".*List<.*String> map\\(.*List<.*MyType> " +
"value\\)\"\\.")
})
@Test
public void shouldNotNestIntoJavaPackageObjects() throws Exception {
}
}

View File

@ -0,0 +1,54 @@
/**
* 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.nestedbeans.exclusions;
import java.util.List;
/**
* @author Filip Hrisafov
*/
class Source {
static class DeepNestedType {
//CHECKSTYLE:OFF
public List<MyType> types;
//CHECKSTYLE:ON
}
static class NestedMyType {
//CHECKSTYLE:OFF
public DeepNestedType deepNestedType;
//CHECKSTYLE:ON
}
static class MyType {
//CHECKSTYLE:OFF
public String someProperty;
//CHECKSTYLE:ON
}
//CHECKSTYLE:OFF
public MyType date;
public MyType calendar;
public List<MyType> types;
//TODO Nested error messages do not work yet. I think that this should be solved as part of #1150
// (or we solve that one first :))
//public NestedMyType nestedMyType;
//CHECKSTYLE:ON
}

View File

@ -0,0 +1,48 @@
/**
* 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.nestedbeans.exclusions;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
/**
* @author Filip Hrisafov
*/
class Target {
class TargetDeepNested {
//CHECKSTYLE:OFF
public List<String> types;
//CHECKSTYLE:ON
}
class TargetNested {
//CHECKSTYLE:OFF
public TargetDeepNested deepNestedType;
//CHECKSTYLE:ON
}
//CHECKSTYLE:OFF
public Date date;
public GregorianCalendar calendar;
public List<String> types;
//public TargetNested nestedMyType;
//CHECKSTYLE:ON
}

View File

@ -0,0 +1,47 @@
/**
* 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.nestedbeans.exclusions.custom;
// tag::documentation[]
import java.util.regex.Pattern;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import org.mapstruct.ap.spi.MappingExclusionProvider;
// end::documentation[]
/**
* @author Filip Hrisafov
*/
// tag::documentation[]
public class CustomMappingExclusionProvider implements MappingExclusionProvider {
private static final Pattern JAVA_JAVAX_PACKAGE = Pattern.compile( "^javax?\\..*" );
@Override
public boolean isExcluded(TypeElement typeElement) {
// end::documentation[]
//For some reason the eclipse compiler does not work when you try to do NestedTarget.class
// tag::documentation[]
Name name = typeElement.getQualifiedName();
return name.length() != 0 && ( JAVA_JAVAX_PACKAGE.matcher( name ).matches() ||
name.toString().equals( "org.mapstruct.ap.test.nestedbeans.exclusions.custom.Target.NestedTarget" ) );
}
}
// end::documentation[]

View File

@ -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.ap.test.nestedbeans.exclusions.custom;
import org.mapstruct.Mapper;
/**
* @author Filip Hrisafov
*/
// tag::documentation[]
@Mapper
public interface ErroneousCustomExclusionMapper {
Target map(Source source);
}
// end::documentation[]

View File

@ -0,0 +1,57 @@
/**
* 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.nestedbeans.exclusions.custom;
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.WithServiceImplementation;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
/**
* @author Filip Hrisafov
*/
@WithClasses({
Source.class,
Target.class,
ErroneousCustomExclusionMapper.class
})
@WithServiceImplementation( CustomMappingExclusionProvider.class )
@RunWith(AnnotationProcessorTestRunner.class)
@IssueKey("1154")
public class ErroneousCustomExclusionTest {
@ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = {
@Diagnostic(type = ErroneousCustomExclusionMapper.class,
kind = javax.tools.Diagnostic.Kind.ERROR,
line = 30,
messageRegExp = "Can't map property \".*NestedSource nested\" to \".*NestedTarget nested\"\\. " +
"Consider to declare/implement a mapping method: \".*NestedTarget map\\(.*NestedSource value\\)" +
"\"\\.")
}
)
@Test
public void shouldFailToCreateMappingForExcludedClass() {
}
}

View File

@ -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.nestedbeans.exclusions.custom;
/**
* @author Filip Hrisafov
*/
// tag::documentation[]
public class Source {
static class NestedSource {
private String property;
// getters and setters
// end::documentation[]
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
// tag::documentation[]
}
private NestedSource nested;
// getters and setters
// end::documentation[]
public NestedSource getNested() {
return nested;
}
public void setNested(NestedSource nested) {
this.nested = nested;
}
// tag::documentation[]
}
// tag::documentation[]

View File

@ -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.nestedbeans.exclusions.custom;
/**
* @author Filip Hrisafov
*/
// tag::documentation[]
public class Target {
static class NestedTarget {
private String property;
// getters and setters
// end::documentation[]
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
// tag::documentation[]
}
private NestedTarget nested;
// getters and setters
// end::documentation[]
public NestedTarget getNested() {
return nested;
}
public void setNested(NestedTarget nested) {
this.nested = nested;
}
// tag::documentation[]
}
// end::documentation[]

View File

@ -18,12 +18,11 @@
*/ */
package org.mapstruct.ap.test.selection.generics; package org.mapstruct.ap.test.selection.generics;
import static org.assertj.core.api.Assertions.assertThat;
import java.math.BigDecimal; import java.math.BigDecimal;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mapstruct.ap.test.NoProperties;
import org.mapstruct.ap.testutil.IssueKey; import org.mapstruct.ap.testutil.IssueKey;
import org.mapstruct.ap.testutil.WithClasses; import org.mapstruct.ap.testutil.WithClasses;
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult; import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
@ -31,6 +30,8 @@ import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome; import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Tests for the invocation of generic methods for mapping bean properties. * Tests for the invocation of generic methods for mapping bean properties.
* *
@ -162,13 +163,18 @@ public class ConversionTest {
} }
@Test @Test
@WithClasses({ ErroneousSource6.class, ErroneousTarget6.class, ErroneousSourceTargetMapper6.class }) @WithClasses({
ErroneousSource6.class,
ErroneousTarget6.class,
ErroneousSourceTargetMapper6.class,
NoProperties.class
})
@ExpectedCompilationOutcome(value = CompilationResult.FAILED, @ExpectedCompilationOutcome(value = CompilationResult.FAILED,
diagnostics = { diagnostics = {
@Diagnostic(type = ErroneousSourceTargetMapper6.class, @Diagnostic(type = ErroneousSourceTargetMapper6.class,
kind = javax.tools.Diagnostic.Kind.ERROR, kind = javax.tools.Diagnostic.Kind.ERROR,
line = 29, line = 29,
messageRegExp = "Can't map property \"java.lang.String " messageRegExp = "Can't map property \".*NoProperties "
+ "foo\\.wrapped\" to" + "foo\\.wrapped\" to"
+ " \"org.mapstruct.ap.test.selection.generics.TypeA " + + " \"org.mapstruct.ap.test.selection.generics.TypeA " +
"foo\\.wrapped\"") "foo\\.wrapped\"")

View File

@ -18,15 +18,17 @@
*/ */
package org.mapstruct.ap.test.selection.generics; package org.mapstruct.ap.test.selection.generics;
import org.mapstruct.ap.test.NoProperties;
public class ErroneousSource6 { public class ErroneousSource6 {
private WildCardSuperWrapper<String> foo; private WildCardSuperWrapper<NoProperties> foo;
public WildCardSuperWrapper<String> getFoo() { public WildCardSuperWrapper<NoProperties> getFoo() {
return foo; return foo;
} }
public void setFoo(WildCardSuperWrapper<String> foo) { public void setFoo(WildCardSuperWrapper<NoProperties> foo) {
this.foo = foo; this.foo = foo;
} }
} }