mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
parent
1c4bbba442
commit
ade4f4d7e2
@ -42,7 +42,6 @@ import org.mapstruct.ap.internal.model.source.MappingOptions;
|
||||
import org.mapstruct.ap.internal.model.source.Method;
|
||||
import org.mapstruct.ap.internal.model.source.SelectionParameters;
|
||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
||||
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.CollectionMappingStrategyPrism;
|
||||
import org.mapstruct.ap.internal.prism.NullValueMappingStrategyPrism;
|
||||
import org.mapstruct.ap.internal.prism.ReportingPolicyPrism;
|
||||
@ -393,7 +392,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
if ( resultType.isAbstract() ) {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
BeanMappingPrism.getInstanceOn( method.getExecutable() ).mirror,
|
||||
method.getMappingOptions().getBeanMapping().getMirror(),
|
||||
BEANMAPPING_ABSTRACT,
|
||||
resultType,
|
||||
method.getResultType()
|
||||
@ -403,7 +402,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
else if ( !resultType.isAssignableTo( method.getResultType() ) ) {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
BeanMappingPrism.getInstanceOn( method.getExecutable() ).mirror,
|
||||
method.getMappingOptions().getBeanMapping().getMirror(),
|
||||
BEANMAPPING_NOT_ASSIGNABLE,
|
||||
resultType,
|
||||
method.getResultType()
|
||||
@ -413,7 +412,7 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
||||
else if ( !resultType.hasEmptyAccessibleConstructor() ) {
|
||||
ctx.getMessager().printMessage(
|
||||
method.getExecutable(),
|
||||
BeanMappingPrism.getInstanceOn( method.getExecutable() ).mirror,
|
||||
method.getMappingOptions().getBeanMapping().getMirror(),
|
||||
Message.GENERAL_NO_SUITABLE_CONSTRUCTOR,
|
||||
resultType
|
||||
);
|
||||
|
@ -6,11 +6,14 @@
|
||||
package org.mapstruct.ap.internal.model.source;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.internal.model.common.TypeFactory;
|
||||
import org.mapstruct.ap.internal.prism.BeanMappingPrism;
|
||||
import org.mapstruct.ap.internal.prism.BuilderPrism;
|
||||
import org.mapstruct.ap.internal.prism.NullValueCheckStrategyPrism;
|
||||
@ -36,87 +39,134 @@ public class BeanMapping {
|
||||
private final BuilderPrism builder;
|
||||
private final NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy;
|
||||
|
||||
private final AnnotationMirror mirror;
|
||||
|
||||
/**
|
||||
* creates a mapping for inheritance. Will set ignoreByDefault to false.
|
||||
* creates a mapping for inheritance. Will set
|
||||
* - ignoreByDefault to false.
|
||||
* - resultType to null
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
* @return new mapping
|
||||
*/
|
||||
public static BeanMapping forInheritance( BeanMapping map ) {
|
||||
public static BeanMapping forInheritance(BeanMapping beanMapping) {
|
||||
return new BeanMapping(
|
||||
map.selectionParameters,
|
||||
map.nullValueMappingStrategy,
|
||||
map.nullValuePropertyMappingStrategy,
|
||||
map.nullValueCheckStrategy,
|
||||
map.reportingPolicy,
|
||||
SelectionParameters.forInheritance( beanMapping.selectionParameters ),
|
||||
beanMapping.nullValueMappingStrategy,
|
||||
beanMapping.nullValuePropertyMappingStrategy,
|
||||
beanMapping.nullValueCheckStrategy,
|
||||
beanMapping.reportingPolicy,
|
||||
false,
|
||||
map.ignoreUnmappedSourceProperties,
|
||||
map.builder
|
||||
beanMapping.ignoreUnmappedSourceProperties,
|
||||
beanMapping.builder,
|
||||
beanMapping.mirror
|
||||
);
|
||||
}
|
||||
|
||||
public static BeanMapping fromPrism(BeanMappingPrism beanMapping, ExecutableElement method,
|
||||
FormattingMessager messager, Types typeUtils) {
|
||||
public static class Builder {
|
||||
|
||||
if ( beanMapping == null ) {
|
||||
return null;
|
||||
private BeanMappingPrism prism;
|
||||
private ExecutableElement method;
|
||||
private FormattingMessager messager;
|
||||
private Types typeUtils;
|
||||
private TypeFactory typeFactory;
|
||||
|
||||
public Builder beanMappingPrism(BeanMappingPrism beanMappingPrism) {
|
||||
this.prism = beanMappingPrism;
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean resultTypeIsDefined = !TypeKind.VOID.equals( beanMapping.resultType().getKind() );
|
||||
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy =
|
||||
null == beanMapping.values.nullValueMappingStrategy()
|
||||
? null
|
||||
: NullValueMappingStrategyPrism.valueOf( beanMapping.nullValueMappingStrategy() );
|
||||
|
||||
NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy =
|
||||
null == beanMapping.values.nullValuePropertyMappingStrategy()
|
||||
? null
|
||||
: NullValuePropertyMappingStrategyPrism.valueOf( beanMapping.nullValuePropertyMappingStrategy() );
|
||||
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategy =
|
||||
null == beanMapping.values.nullValueCheckStrategy()
|
||||
? null
|
||||
: NullValueCheckStrategyPrism.valueOf( beanMapping.nullValueCheckStrategy() );
|
||||
|
||||
boolean ignoreByDefault = beanMapping.ignoreByDefault();
|
||||
BuilderPrism builderMapping = null;
|
||||
if ( beanMapping.values.builder() != null ) {
|
||||
builderMapping = beanMapping.builder();
|
||||
public Builder method(ExecutableElement method) {
|
||||
this.method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
if ( !resultTypeIsDefined && beanMapping.qualifiedBy().isEmpty() && beanMapping.qualifiedByName().isEmpty()
|
||||
&& beanMapping.ignoreUnmappedSourceProperties().isEmpty()
|
||||
&& ( nullValueMappingStrategy == null ) && ( nullValuePropertyMappingStrategy == null )
|
||||
&& ( nullValueCheckStrategy == null ) && !ignoreByDefault && builderMapping == null ) {
|
||||
|
||||
messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS );
|
||||
public Builder messager(FormattingMessager messager) {
|
||||
this.messager = messager;
|
||||
return this;
|
||||
}
|
||||
|
||||
SelectionParameters cmp = new SelectionParameters(
|
||||
beanMapping.qualifiedBy(),
|
||||
beanMapping.qualifiedByName(),
|
||||
resultTypeIsDefined ? beanMapping.resultType() : null,
|
||||
typeUtils
|
||||
);
|
||||
public Builder typeUtils(Types typeUtils) {
|
||||
this.typeUtils = typeUtils;
|
||||
return this;
|
||||
}
|
||||
|
||||
//TODO Do we want to add the reporting policy to the BeanMapping as well? To give more granular support?
|
||||
return new BeanMapping(
|
||||
cmp,
|
||||
nullValueMappingStrategy,
|
||||
nullValuePropertyMappingStrategy,
|
||||
nullValueCheckStrategy,
|
||||
null,
|
||||
ignoreByDefault,
|
||||
beanMapping.ignoreUnmappedSourceProperties(),
|
||||
builderMapping
|
||||
);
|
||||
public Builder typeFactory(TypeFactory typeFactory) {
|
||||
this.typeFactory = typeFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BeanMapping build() {
|
||||
|
||||
if ( prism == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Objects.requireNonNull( method );
|
||||
Objects.requireNonNull( messager );
|
||||
Objects.requireNonNull( method );
|
||||
Objects.requireNonNull( typeUtils );
|
||||
Objects.requireNonNull( typeFactory );
|
||||
|
||||
boolean resultTypeIsDefined = !TypeKind.VOID.equals( prism.resultType().getKind() );
|
||||
|
||||
NullValueMappingStrategyPrism nullValueMappingStrategy =
|
||||
null == prism.values.nullValueMappingStrategy()
|
||||
? null
|
||||
: NullValueMappingStrategyPrism.valueOf( prism.nullValueMappingStrategy() );
|
||||
|
||||
NullValuePropertyMappingStrategyPrism nullValuePropertyMappingStrategy =
|
||||
null == prism.values.nullValuePropertyMappingStrategy()
|
||||
? null
|
||||
:
|
||||
NullValuePropertyMappingStrategyPrism.valueOf( prism.nullValuePropertyMappingStrategy() );
|
||||
|
||||
NullValueCheckStrategyPrism nullValueCheckStrategy =
|
||||
null == prism.values.nullValueCheckStrategy()
|
||||
? null
|
||||
: NullValueCheckStrategyPrism.valueOf( prism.nullValueCheckStrategy() );
|
||||
|
||||
boolean ignoreByDefault = prism.ignoreByDefault();
|
||||
BuilderPrism builderMapping = null;
|
||||
if ( prism.values.builder() != null ) {
|
||||
builderMapping = prism.builder();
|
||||
}
|
||||
|
||||
if ( !resultTypeIsDefined && prism.qualifiedBy().isEmpty() &&
|
||||
prism.qualifiedByName().isEmpty()
|
||||
&& prism.ignoreUnmappedSourceProperties().isEmpty()
|
||||
&& ( nullValueMappingStrategy == null ) && ( nullValuePropertyMappingStrategy == null )
|
||||
&& ( nullValueCheckStrategy == null ) && !ignoreByDefault && builderMapping == null ) {
|
||||
|
||||
messager.printMessage( method, Message.BEANMAPPING_NO_ELEMENTS );
|
||||
}
|
||||
|
||||
SelectionParameters cmp = new SelectionParameters(
|
||||
prism.qualifiedBy(),
|
||||
prism.qualifiedByName(),
|
||||
resultTypeIsDefined ? prism.resultType() : null,
|
||||
typeUtils
|
||||
);
|
||||
|
||||
//TODO Do we want to add the reporting policy to the BeanMapping as well? To give more granular support?
|
||||
return new BeanMapping(
|
||||
cmp,
|
||||
nullValueMappingStrategy,
|
||||
nullValuePropertyMappingStrategy,
|
||||
nullValueCheckStrategy,
|
||||
null,
|
||||
ignoreByDefault,
|
||||
prism.ignoreUnmappedSourceProperties(),
|
||||
builderMapping,
|
||||
prism.mirror
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private BeanMapping(SelectionParameters selectionParameters, NullValueMappingStrategyPrism nvms,
|
||||
NullValuePropertyMappingStrategyPrism nvpms, NullValueCheckStrategyPrism nvcs,
|
||||
ReportingPolicyPrism reportingPolicy, boolean ignoreByDefault,
|
||||
List<String> ignoreUnmappedSourceProperties, BuilderPrism builder) {
|
||||
List<String> ignoreUnmappedSourceProperties, BuilderPrism builder,
|
||||
AnnotationMirror mirror) {
|
||||
this.selectionParameters = selectionParameters;
|
||||
this.nullValueMappingStrategy = nvms;
|
||||
this.nullValuePropertyMappingStrategy = nvpms;
|
||||
@ -125,6 +175,7 @@ public class BeanMapping {
|
||||
this.ignoreByDefault = ignoreByDefault;
|
||||
this.ignoreUnmappedSourceProperties = ignoreUnmappedSourceProperties;
|
||||
this.builder = builder;
|
||||
this.mirror = mirror;
|
||||
}
|
||||
|
||||
public SelectionParameters getSelectionParameters() {
|
||||
@ -155,6 +206,10 @@ public class BeanMapping {
|
||||
return ignoreUnmappedSourceProperties;
|
||||
}
|
||||
|
||||
public AnnotationMirror getMirror() {
|
||||
return mirror;
|
||||
}
|
||||
|
||||
/**
|
||||
* derives the builder prism given the options and configuration
|
||||
* @param method containing mandatory configuration and the mapping options (optionally containing a beanmapping)
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.internal.model.source;
|
||||
|
||||
/**
|
||||
* Represents the mapping between one enum constant and another.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class EnumMapping {
|
||||
|
||||
private final String source;
|
||||
private final String target;
|
||||
|
||||
public EnumMapping(String source, String target) {
|
||||
this.source = source;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the constant in the source enum.
|
||||
*/
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name of the constant in the target enum.
|
||||
*/
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
}
|
@ -26,6 +26,23 @@ public class SelectionParameters {
|
||||
private final Types typeUtils;
|
||||
private final SourceRHS sourceRHS;
|
||||
|
||||
/**
|
||||
* Returns new selection parameters
|
||||
*
|
||||
* ResultType is not inherited.
|
||||
*
|
||||
* @param selectionParameters
|
||||
* @return
|
||||
*/
|
||||
public static SelectionParameters forInheritance(SelectionParameters selectionParameters) {
|
||||
return new SelectionParameters(
|
||||
selectionParameters.qualifiers,
|
||||
selectionParameters.qualifyingNames,
|
||||
null,
|
||||
selectionParameters.typeUtils
|
||||
);
|
||||
}
|
||||
|
||||
public SelectionParameters(List<TypeMirror> qualifiers, List<String> qualifyingNames, TypeMirror resultType,
|
||||
Types typeUtils) {
|
||||
this( qualifiers, qualifyingNames, resultType, typeUtils, null );
|
||||
|
@ -254,7 +254,14 @@ public class MethodRetrievalProcessor implements ModelElementProcessor<Void, Lis
|
||||
.setMapMapping(
|
||||
MapMapping.fromPrism( MapMappingPrism.getInstanceOn( method ), method, messager, typeUtils ) )
|
||||
.setBeanMapping(
|
||||
BeanMapping.fromPrism( BeanMappingPrism.getInstanceOn( method ), method, messager, typeUtils ) )
|
||||
new BeanMapping.Builder()
|
||||
.beanMappingPrism( BeanMappingPrism.getInstanceOn( method ) )
|
||||
.messager( messager )
|
||||
.method( method )
|
||||
.typeUtils( typeUtils )
|
||||
.typeFactory( typeFactory )
|
||||
.build()
|
||||
)
|
||||
.setValueMappings( getValueMappings( method ) )
|
||||
.setTypeUtils( typeUtils )
|
||||
.setTypeFactory( typeFactory )
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.bugs._1821;
|
||||
|
||||
import org.mapstruct.BeanMapping;
|
||||
import org.mapstruct.InheritConfiguration;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface Issue1821Mapper {
|
||||
|
||||
Issue1821Mapper INSTANCE = Mappers.getMapper( Issue1821Mapper.class );
|
||||
|
||||
@BeanMapping( resultType = Target.class )
|
||||
Target map(Source source);
|
||||
|
||||
@InheritConfiguration( name = "map" )
|
||||
ExtendedTarget mapExtended(Source source);
|
||||
|
||||
class Target {
|
||||
}
|
||||
|
||||
class ExtendedTarget extends Target {
|
||||
}
|
||||
|
||||
class Source {
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright MapStruct Authors.
|
||||
*
|
||||
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package org.mapstruct.ap.test.bugs._1821;
|
||||
|
||||
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;
|
||||
|
||||
@IssueKey("1797")
|
||||
@RunWith( AnnotationProcessorTestRunner.class)
|
||||
@WithClasses( Issue1821Mapper.class )
|
||||
public class Issue1821Test {
|
||||
|
||||
@Test
|
||||
public void shouldNotGiveNullPtr() {
|
||||
Issue1821Mapper.INSTANCE.map( new Issue1821Mapper.Source() );
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user