mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
Refactoring of BeanMapping and Source/TargetReferences (common base class) (#1903)
This commit is contained in:
parent
6d9a50601e
commit
e12f9ffd7b
@ -19,7 +19,6 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javax.lang.model.type.DeclaredType;
|
import javax.lang.model.type.DeclaredType;
|
||||||
import javax.tools.Diagnostic;
|
import javax.tools.Diagnostic;
|
||||||
@ -52,7 +51,6 @@ import org.mapstruct.ap.internal.util.Message;
|
|||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
import org.mapstruct.ap.internal.util.accessor.Accessor;
|
||||||
|
|
||||||
import static org.mapstruct.ap.internal.model.source.Mapping.getMappingByTargetName;
|
|
||||||
import static org.mapstruct.ap.internal.model.beanmapping.MappingReferences.forSourceMethod;
|
import static org.mapstruct.ap.internal.model.beanmapping.MappingReferences.forSourceMethod;
|
||||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||||
import static org.mapstruct.ap.internal.util.Message.BEANMAPPING_ABSTRACT;
|
import static org.mapstruct.ap.internal.util.Message.BEANMAPPING_ABSTRACT;
|
||||||
@ -88,7 +86,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
private final Set<Parameter> unprocessedSourceParameters = new HashSet<>();
|
private final Set<Parameter> unprocessedSourceParameters = new HashSet<>();
|
||||||
private final Set<String> existingVariableNames = new HashSet<>();
|
private final Set<String> existingVariableNames = new HashSet<>();
|
||||||
private final Map<String, Set<MappingReference>> unprocessedDefinedTargets = new LinkedHashMap<>();
|
private final Map<String, Set<MappingReference>> unprocessedDefinedTargets = new LinkedHashMap<>();
|
||||||
private Function<String, Mapping> singleMapping;
|
|
||||||
|
|
||||||
private MappingReferences mappingReferences;
|
private MappingReferences mappingReferences;
|
||||||
|
|
||||||
@ -103,15 +100,12 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Builder sourceMethod(SourceMethod sourceMethod) {
|
public Builder sourceMethod(SourceMethod sourceMethod) {
|
||||||
singleMapping =
|
|
||||||
targetName -> getMappingByTargetName( targetName, sourceMethod.getMappingOptions().getMappings() );
|
|
||||||
this.method = sourceMethod;
|
this.method = sourceMethod;
|
||||||
this.mappingReferences = forSourceMethod( sourceMethod, ctx.getMessager(), ctx.getTypeFactory() );
|
this.mappingReferences = forSourceMethod( sourceMethod, ctx.getMessager(), ctx.getTypeFactory() );
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder forgedMethod(ForgedMethod forgedMethod) {
|
public Builder forgedMethod(ForgedMethod forgedMethod) {
|
||||||
singleMapping = targetPropertyName -> null;
|
|
||||||
this.method = forgedMethod;
|
this.method = forgedMethod;
|
||||||
mappingReferences = forgedMethod.getMappingReferences();
|
mappingReferences = forgedMethod.getMappingReferences();
|
||||||
Parameter sourceParameter = first( Parameter.getSourceParameters( forgedMethod.getParameters() ) );
|
Parameter sourceParameter = first( Parameter.getSourceParameters( forgedMethod.getParameters() ) );
|
||||||
@ -320,12 +314,14 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
.name( propertyName )
|
.name( propertyName )
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
Accessor targetPropertyReadAccessor =
|
||||||
|
method.getResultType().getPropertyReadAccessors().get( propertyName );
|
||||||
MappingReferences mappingRefs = extractMappingReferences( propertyName, true );
|
MappingReferences mappingRefs = extractMappingReferences( propertyName, true );
|
||||||
PropertyMapping propertyMapping = new PropertyMappingBuilder()
|
PropertyMapping propertyMapping = new PropertyMappingBuilder()
|
||||||
.mappingContext( ctx )
|
.mappingContext( ctx )
|
||||||
.sourceMethod( method )
|
.sourceMethod( method )
|
||||||
.targetWriteAccessor( unprocessedTargetProperties.get( propertyName ) )
|
.targetWriteAccessor( unprocessedTargetProperties.get( propertyName ) )
|
||||||
.targetReadAccessor( getTargetPropertyReadAccessor( propertyName ) )
|
.targetReadAccessor( targetPropertyReadAccessor )
|
||||||
.targetPropertyName( propertyName )
|
.targetPropertyName( propertyName )
|
||||||
.sourceReference( reference )
|
.sourceReference( reference )
|
||||||
.existingVariableNames( existingVariableNames )
|
.existingVariableNames( existingVariableNames )
|
||||||
@ -480,18 +476,16 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ( MappingReference mapping : mappingReferences.getMappingReferences() ) {
|
for ( MappingReference mapping : mappingReferences.getMappingReferences() ) {
|
||||||
TargetReference targetReference = mapping.getTargetReference();
|
if ( mapping.isValid() ) {
|
||||||
if ( targetReference.isValid() ) {
|
String target = mapping.getTargetReference().getShallowestPropertyName();
|
||||||
String target = first( targetReference.getPropertyEntries() ).getFullName();
|
|
||||||
if ( !handledTargets.contains( target ) ) {
|
if ( !handledTargets.contains( target ) ) {
|
||||||
if ( handleDefinedMapping( mapping, handledTargets ) ) {
|
if ( handleDefinedMapping( mapping, handledTargets ) ) {
|
||||||
errorOccurred = true;
|
errorOccurred = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( mapping.getSourceReference() != null && mapping.getSourceReference().isValid() ) {
|
if ( mapping.getSourceReference() != null ) {
|
||||||
List<PropertyEntry> sourceEntries = mapping.getSourceReference().getPropertyEntries();
|
String source = mapping.getSourceReference().getShallowestPropertyName();
|
||||||
if ( !sourceEntries.isEmpty() ) {
|
if ( source != null ) {
|
||||||
String source = first( sourceEntries ).getFullName();
|
|
||||||
unprocessedSourceProperties.remove( source );
|
unprocessedSourceProperties.remove( source );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,6 +552,11 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if source / expression / constant are not somehow handled already
|
||||||
|
if ( unprocessedDefinedTargets.containsKey( targetPropertyName ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// check the mapping options
|
// check the mapping options
|
||||||
// its an ignored property mapping
|
// its an ignored property mapping
|
||||||
if ( mapping.isIgnored() ) {
|
if ( mapping.isIgnored() ) {
|
||||||
@ -565,11 +564,52 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
handledTargets.add( targetProperty.getName() );
|
handledTargets.add( targetProperty.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// its a constant
|
||||||
|
// if we have an unprocessed target that means that it most probably is nested and we should
|
||||||
|
// not generated any mapping for it now. Eventually it will be done though
|
||||||
|
else if ( mapping.getConstant() != null ) {
|
||||||
|
|
||||||
|
propertyMapping = new ConstantMappingBuilder()
|
||||||
|
.mappingContext( ctx )
|
||||||
|
.sourceMethod( method )
|
||||||
|
.constantExpression( mapping.getConstant() )
|
||||||
|
.targetProperty( targetProperty )
|
||||||
|
.targetPropertyName( targetPropertyName )
|
||||||
|
.formattingParameters( mapping.getFormattingParameters() )
|
||||||
|
.selectionParameters( mapping.getSelectionParameters() )
|
||||||
|
.existingVariableNames( existingVariableNames )
|
||||||
|
.dependsOn( mapping.getDependsOn() )
|
||||||
|
.mirror( mapping.getMirror() )
|
||||||
|
.build();
|
||||||
|
handledTargets.add( targetPropertyName );
|
||||||
|
}
|
||||||
|
|
||||||
|
// its an expression
|
||||||
|
// if we have an unprocessed target that means that it most probably is nested and we should
|
||||||
|
// not generated any mapping for it now. Eventually it will be done though
|
||||||
|
else if ( mapping.getJavaExpression() != null ) {
|
||||||
|
|
||||||
|
propertyMapping = new JavaExpressionMappingBuilder()
|
||||||
|
.mappingContext( ctx )
|
||||||
|
.sourceMethod( method )
|
||||||
|
.javaExpression( mapping.getJavaExpression() )
|
||||||
|
.existingVariableNames( existingVariableNames )
|
||||||
|
.targetProperty( targetProperty )
|
||||||
|
.targetPropertyName( targetPropertyName )
|
||||||
|
.dependsOn( mapping.getDependsOn() )
|
||||||
|
.mirror( mapping.getMirror() )
|
||||||
|
.build();
|
||||||
|
handledTargets.add( targetPropertyName );
|
||||||
|
}
|
||||||
// its a plain-old property mapping
|
// its a plain-old property mapping
|
||||||
else if ( mapping.getSourceName() != null ) {
|
else {
|
||||||
|
|
||||||
// determine source parameter
|
// determine source parameter
|
||||||
SourceReference sourceRef = mappingRef.getSourceReference();
|
SourceReference sourceRef = mappingRef.getSourceReference();
|
||||||
|
if ( sourceRef == null && method.getSourceParameters().size() == 1 ) {
|
||||||
|
sourceRef = getSourceRef( method.getSourceParameters().get( 0 ), targetPropertyName );
|
||||||
|
}
|
||||||
|
|
||||||
if ( sourceRef.isValid() ) {
|
if ( sourceRef.isValid() ) {
|
||||||
|
|
||||||
// targetProperty == null can occur: we arrived here because we want as many errors
|
// targetProperty == null can occur: we arrived here because we want as many errors
|
||||||
@ -598,46 +638,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
errorOccured = true;
|
errorOccured = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// its a constant
|
|
||||||
// if we have an unprocessed target that means that it most probably is nested and we should
|
|
||||||
// not generated any mapping for it now. Eventually it will be done though
|
|
||||||
else if ( mapping.getConstant() != null && !unprocessedDefinedTargets.containsKey( targetPropertyName ) ) {
|
|
||||||
|
|
||||||
propertyMapping = new ConstantMappingBuilder()
|
|
||||||
.mappingContext( ctx )
|
|
||||||
.sourceMethod( method )
|
|
||||||
.constantExpression( mapping.getConstant() )
|
|
||||||
.targetProperty( targetProperty )
|
|
||||||
.targetPropertyName( targetPropertyName )
|
|
||||||
.formattingParameters( mapping.getFormattingParameters() )
|
|
||||||
.selectionParameters( mapping.getSelectionParameters() )
|
|
||||||
.existingVariableNames( existingVariableNames )
|
|
||||||
.dependsOn( mapping.getDependsOn() )
|
|
||||||
.mirror( mapping.getMirror() )
|
|
||||||
.build();
|
|
||||||
handledTargets.add( targetPropertyName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// its an expression
|
|
||||||
// if we have an unprocessed target that means that it most probably is nested and we should
|
|
||||||
// not generated any mapping for it now. Eventually it will be done though
|
|
||||||
else if ( mapping.getJavaExpression() != null
|
|
||||||
&& !unprocessedDefinedTargets.containsKey( targetPropertyName ) ) {
|
|
||||||
|
|
||||||
propertyMapping = new JavaExpressionMappingBuilder()
|
|
||||||
.mappingContext( ctx )
|
|
||||||
.sourceMethod( method )
|
|
||||||
.javaExpression( mapping.getJavaExpression() )
|
|
||||||
.existingVariableNames( existingVariableNames )
|
|
||||||
.targetProperty( targetProperty )
|
|
||||||
.targetPropertyName( targetPropertyName )
|
|
||||||
.dependsOn( mapping.getDependsOn() )
|
|
||||||
.mirror( mapping.getMirror() )
|
|
||||||
.build();
|
|
||||||
handledTargets.add( targetPropertyName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// remaining are the mappings without a 'source' so, 'only' a date format or qualifiers
|
// remaining are the mappings without a 'source' so, 'only' a date format or qualifiers
|
||||||
if ( propertyMapping != null ) {
|
if ( propertyMapping != null ) {
|
||||||
propertyMappings.add( propertyMapping );
|
propertyMappings.add( propertyMapping );
|
||||||
@ -653,91 +653,60 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
* the set of remaining target properties.
|
* the set of remaining target properties.
|
||||||
*/
|
*/
|
||||||
private void applyPropertyNameBasedMapping() {
|
private void applyPropertyNameBasedMapping() {
|
||||||
|
List<SourceReference> sourceReferences = new ArrayList<>();
|
||||||
Iterator<Entry<String, Accessor>> targetPropertyEntriesIterator =
|
for ( String targetPropertyName : unprocessedTargetProperties.keySet() ) {
|
||||||
unprocessedTargetProperties.entrySet().iterator();
|
for ( Parameter sourceParameter : method.getSourceParameters() ) {
|
||||||
|
SourceReference sourceRef = getSourceRef( sourceParameter, targetPropertyName );
|
||||||
while ( targetPropertyEntriesIterator.hasNext() ) {
|
if ( sourceRef != null ) {
|
||||||
|
sourceReferences.add( sourceRef );
|
||||||
Entry<String, Accessor> targetProperty = targetPropertyEntriesIterator.next();
|
|
||||||
String targetPropertyName = targetProperty.getKey();
|
|
||||||
|
|
||||||
PropertyMapping propertyMapping = null;
|
|
||||||
|
|
||||||
if ( propertyMapping == null ) {
|
|
||||||
|
|
||||||
for ( Parameter sourceParameter : method.getSourceParameters() ) {
|
|
||||||
|
|
||||||
Type sourceType = sourceParameter.getType();
|
|
||||||
|
|
||||||
if ( sourceType.isPrimitive() || sourceType.isArrayType() ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyMapping newPropertyMapping = null;
|
|
||||||
|
|
||||||
Accessor sourceReadAccessor =
|
|
||||||
sourceParameter.getType().getPropertyReadAccessors().get( targetPropertyName );
|
|
||||||
|
|
||||||
Accessor sourcePresenceChecker =
|
|
||||||
sourceParameter.getType().getPropertyPresenceCheckers().get( targetPropertyName );
|
|
||||||
|
|
||||||
if ( sourceReadAccessor != null ) {
|
|
||||||
Mapping mapping = singleMapping.apply( targetProperty.getKey() );
|
|
||||||
DeclaredType declaredSourceType = (DeclaredType) sourceParameter.getType().getTypeMirror();
|
|
||||||
|
|
||||||
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
|
|
||||||
.sourceParameter( sourceParameter )
|
|
||||||
.type( ctx.getTypeFactory().getReturnType( declaredSourceType, sourceReadAccessor ) )
|
|
||||||
.readAccessor( sourceReadAccessor )
|
|
||||||
.presenceChecker( sourcePresenceChecker )
|
|
||||||
.name( targetProperty.getKey() )
|
|
||||||
.build();
|
|
||||||
|
|
||||||
MappingReferences mappingRefs = extractMappingReferences( targetPropertyName, false );
|
|
||||||
newPropertyMapping = new PropertyMappingBuilder()
|
|
||||||
.mappingContext( ctx )
|
|
||||||
.sourceMethod( method )
|
|
||||||
.targetWriteAccessor( targetProperty.getValue() )
|
|
||||||
.targetReadAccessor( getTargetPropertyReadAccessor( targetPropertyName ) )
|
|
||||||
.targetPropertyName( targetPropertyName )
|
|
||||||
.sourceReference( sourceRef )
|
|
||||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
|
||||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
|
||||||
.defaultValue( mapping != null ? mapping.getDefaultValue() : null )
|
|
||||||
.existingVariableNames( existingVariableNames )
|
|
||||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptySet() )
|
|
||||||
.forgeMethodWithMappingReferences( mappingRefs )
|
|
||||||
.nullValueCheckStrategy( mapping != null ? mapping.getNullValueCheckStrategy() : null )
|
|
||||||
.nullValuePropertyMappingStrategy( mapping != null ?
|
|
||||||
mapping.getNullValuePropertyMappingStrategy() : null )
|
|
||||||
.mirror( mapping != null ? mapping.getMirror() : null )
|
|
||||||
.build();
|
|
||||||
|
|
||||||
unprocessedSourceParameters.remove( sourceParameter );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( propertyMapping != null && newPropertyMapping != null ) {
|
|
||||||
// TODO improve error message
|
|
||||||
ctx.getMessager().printMessage(
|
|
||||||
method.getExecutable(),
|
|
||||||
Message.BEANMAPPING_SEVERAL_POSSIBLE_SOURCES,
|
|
||||||
targetPropertyName
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if ( newPropertyMapping != null ) {
|
|
||||||
propertyMapping = newPropertyMapping;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
applyPropertyNameBasedMapping( sourceReferences );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over all target properties and all source parameters.
|
||||||
|
* <p>
|
||||||
|
* When a property name match occurs, the remainder will be checked for duplicates. Matches will be removed from
|
||||||
|
* the set of remaining target properties.
|
||||||
|
*/
|
||||||
|
private void applyPropertyNameBasedMapping(List<SourceReference> sourceReferences) {
|
||||||
|
|
||||||
|
for ( SourceReference sourceRef : sourceReferences ) {
|
||||||
|
|
||||||
|
String targetPropertyName = sourceRef.getDeepestPropertyName();
|
||||||
|
Accessor targetPropertyWriteAccessor = unprocessedTargetProperties.remove( targetPropertyName );
|
||||||
|
if ( targetPropertyWriteAccessor == null ) {
|
||||||
|
// TODO improve error message
|
||||||
|
ctx.getMessager()
|
||||||
|
.printMessage( method.getExecutable(),
|
||||||
|
Message.BEANMAPPING_SEVERAL_POSSIBLE_SOURCES,
|
||||||
|
targetPropertyName
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accessor targetPropertyReadAccessor =
|
||||||
|
method.getResultType().getPropertyReadAccessors().get( targetPropertyName );
|
||||||
|
MappingReferences mappingRefs = extractMappingReferences( targetPropertyName, false );
|
||||||
|
PropertyMapping propertyMapping = new PropertyMappingBuilder().mappingContext( ctx )
|
||||||
|
.sourceMethod( method )
|
||||||
|
.targetWriteAccessor( targetPropertyWriteAccessor )
|
||||||
|
.targetReadAccessor( targetPropertyReadAccessor )
|
||||||
|
.targetPropertyName( targetPropertyName )
|
||||||
|
.sourceReference( sourceRef )
|
||||||
|
.existingVariableNames( existingVariableNames )
|
||||||
|
.forgeMethodWithMappingReferences( mappingRefs )
|
||||||
|
.build();
|
||||||
|
|
||||||
|
unprocessedSourceParameters.remove( sourceRef.getParameter() );
|
||||||
|
|
||||||
if ( propertyMapping != null ) {
|
if ( propertyMapping != null ) {
|
||||||
propertyMappings.add( propertyMapping );
|
propertyMappings.add( propertyMapping );
|
||||||
targetPropertyEntriesIterator.remove();
|
|
||||||
unprocessedDefinedTargets.remove( targetPropertyName );
|
|
||||||
unprocessedSourceProperties.remove( targetPropertyName );
|
|
||||||
}
|
}
|
||||||
|
unprocessedDefinedTargets.remove( targetPropertyName );
|
||||||
|
unprocessedSourceProperties.remove( targetPropertyName );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,30 +725,24 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
|
|
||||||
Parameter sourceParameter = sourceParameters.next();
|
Parameter sourceParameter = sourceParameters.next();
|
||||||
if ( sourceParameter.getName().equals( targetProperty.getKey() ) ) {
|
if ( sourceParameter.getName().equals( targetProperty.getKey() ) ) {
|
||||||
Mapping mapping = singleMapping.apply( targetProperty.getKey() );
|
|
||||||
|
|
||||||
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
|
SourceReference sourceRef = new SourceReference.BuilderFromProperty()
|
||||||
.sourceParameter( sourceParameter )
|
.sourceParameter( sourceParameter )
|
||||||
.name( targetProperty.getKey() )
|
.name( targetProperty.getKey() )
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
Accessor targetPropertyReadAccessor =
|
||||||
|
method.getResultType().getPropertyReadAccessors().get( targetProperty.getKey() );
|
||||||
MappingReferences mappingRefs = extractMappingReferences( targetProperty.getKey(), false );
|
MappingReferences mappingRefs = extractMappingReferences( targetProperty.getKey(), false );
|
||||||
PropertyMapping propertyMapping = new PropertyMappingBuilder()
|
PropertyMapping propertyMapping = new PropertyMappingBuilder()
|
||||||
.mappingContext( ctx )
|
.mappingContext( ctx )
|
||||||
.sourceMethod( method )
|
.sourceMethod( method )
|
||||||
.targetWriteAccessor( targetProperty.getValue() )
|
.targetWriteAccessor( targetProperty.getValue() )
|
||||||
.targetReadAccessor( getTargetPropertyReadAccessor( targetProperty.getKey() ) )
|
.targetReadAccessor( targetPropertyReadAccessor )
|
||||||
.targetPropertyName( targetProperty.getKey() )
|
.targetPropertyName( targetProperty.getKey() )
|
||||||
.sourceReference( sourceRef )
|
.sourceReference( sourceRef )
|
||||||
.formattingParameters( mapping != null ? mapping.getFormattingParameters() : null )
|
|
||||||
.selectionParameters( mapping != null ? mapping.getSelectionParameters() : null )
|
|
||||||
.existingVariableNames( existingVariableNames )
|
.existingVariableNames( existingVariableNames )
|
||||||
.dependsOn( mapping != null ? mapping.getDependsOn() : Collections.<String>emptySet() )
|
|
||||||
.forgeMethodWithMappingReferences( mappingRefs )
|
.forgeMethodWithMappingReferences( mappingRefs )
|
||||||
.nullValueCheckStrategy( mapping != null ? mapping.getNullValueCheckStrategy() : null )
|
|
||||||
.nullValuePropertyMappingStrategy( mapping != null ?
|
|
||||||
mapping.getNullValuePropertyMappingStrategy() : null )
|
|
||||||
.mirror( mapping != null ? mapping.getMirror() : null )
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
propertyMappings.add( propertyMapping );
|
propertyMappings.add( propertyMapping );
|
||||||
@ -792,6 +755,33 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SourceReference getSourceRef(Parameter sourceParameter, String targetPropertyName) {
|
||||||
|
|
||||||
|
SourceReference sourceRef = null;
|
||||||
|
|
||||||
|
if ( sourceParameter.getType().isPrimitive() || sourceParameter.getType().isArrayType() ) {
|
||||||
|
return sourceRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
Accessor sourceReadAccessor =
|
||||||
|
sourceParameter.getType().getPropertyReadAccessors().get( targetPropertyName );
|
||||||
|
|
||||||
|
Accessor sourcePresenceChecker =
|
||||||
|
sourceParameter.getType().getPropertyPresenceCheckers().get( targetPropertyName );
|
||||||
|
|
||||||
|
if ( sourceReadAccessor != null ) {
|
||||||
|
DeclaredType declaredSourceType = (DeclaredType) sourceParameter.getType().getTypeMirror();
|
||||||
|
Type returnType = ctx.getTypeFactory().getReturnType( declaredSourceType, sourceReadAccessor );
|
||||||
|
sourceRef = new SourceReference.BuilderFromProperty().sourceParameter( sourceParameter )
|
||||||
|
.type( returnType )
|
||||||
|
.readAccessor( sourceReadAccessor )
|
||||||
|
.presenceChecker( sourcePresenceChecker )
|
||||||
|
.name( targetPropertyName )
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return sourceRef;
|
||||||
|
}
|
||||||
|
|
||||||
private MappingReferences extractMappingReferences(String targetProperty, boolean restrictToDefinedMappings) {
|
private MappingReferences extractMappingReferences(String targetProperty, boolean restrictToDefinedMappings) {
|
||||||
if ( unprocessedDefinedTargets.containsKey( targetProperty ) ) {
|
if ( unprocessedDefinedTargets.containsKey( targetProperty ) ) {
|
||||||
Set<MappingReference> mappings = unprocessedDefinedTargets.get( targetProperty );
|
Set<MappingReference> mappings = unprocessedDefinedTargets.get( targetProperty );
|
||||||
@ -800,10 +790,6 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Accessor getTargetPropertyReadAccessor(String propertyName) {
|
|
||||||
return method.getResultType().getPropertyReadAccessors().get( propertyName );
|
|
||||||
}
|
|
||||||
|
|
||||||
private ReportingPolicyPrism getUnmappedTargetPolicy() {
|
private ReportingPolicyPrism getUnmappedTargetPolicy() {
|
||||||
if ( mappingReferences.isForForgedMethods() ) {
|
if ( mappingReferences.isForForgedMethods() ) {
|
||||||
return ReportingPolicyPrism.IGNORE;
|
return ReportingPolicyPrism.IGNORE;
|
||||||
@ -1034,10 +1020,5 @@ public class BeanMappingMethod extends NormalTypeMappingMethod {
|
|||||||
return Objects.equals( propertyMappings, that.propertyMappings );
|
return Objects.equals( propertyMappings, that.propertyMappings );
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface SingleMappingByTargetPropertyNameFunction {
|
|
||||||
|
|
||||||
Mapping getSingleMappingByTargetPropertyName(String targetPropertyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@ import static org.mapstruct.ap.internal.model.ForgedMethod.forElementMapping;
|
|||||||
import static org.mapstruct.ap.internal.model.ForgedMethod.forPropertyMapping;
|
import static org.mapstruct.ap.internal.model.ForgedMethod.forPropertyMapping;
|
||||||
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_DEFAULT;
|
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_DEFAULT;
|
||||||
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_NULL;
|
import static org.mapstruct.ap.internal.prism.NullValuePropertyMappingStrategyPrism.SET_TO_NULL;
|
||||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
|
||||||
import static org.mapstruct.ap.internal.util.Collections.last;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to
|
* Represents the mapping between a source and target property, e.g. from {@code String Source#foo} to
|
||||||
@ -519,10 +517,10 @@ public class PropertyMapping extends ModelElement {
|
|||||||
|
|
||||||
private SourceRHS getSourceRHS( SourceReference sourceReference ) {
|
private SourceRHS getSourceRHS( SourceReference sourceReference ) {
|
||||||
Parameter sourceParam = sourceReference.getParameter();
|
Parameter sourceParam = sourceReference.getParameter();
|
||||||
List<PropertyEntry> propertyEntries = sourceReference.getPropertyEntries();
|
PropertyEntry propertyEntry = sourceReference.getDeepestProperty();
|
||||||
|
|
||||||
// parameter reference
|
// parameter reference
|
||||||
if ( propertyEntries.isEmpty() ) {
|
if ( propertyEntry == null ) {
|
||||||
return new SourceRHS( sourceParam.getName(),
|
return new SourceRHS( sourceParam.getName(),
|
||||||
sourceParam.getType(),
|
sourceParam.getType(),
|
||||||
existingVariableNames,
|
existingVariableNames,
|
||||||
@ -530,8 +528,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
// simple property
|
// simple property
|
||||||
else if ( propertyEntries.size() == 1 ) {
|
else if ( !sourceReference.isNested() ) {
|
||||||
PropertyEntry propertyEntry = propertyEntries.get( 0 );
|
|
||||||
String sourceRef = sourceParam.getName() + "." + ValueProvider.of( propertyEntry.getReadAccessor() );
|
String sourceRef = sourceParam.getName() + "." + ValueProvider.of( propertyEntry.getReadAccessor() );
|
||||||
return new SourceRHS( sourceParam.getName(),
|
return new SourceRHS( sourceParam.getName(),
|
||||||
sourceRef,
|
sourceRef,
|
||||||
@ -543,7 +540,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
}
|
}
|
||||||
// nested property given as dot path
|
// nested property given as dot path
|
||||||
else {
|
else {
|
||||||
Type sourceType = last( propertyEntries ).getType();
|
Type sourceType = propertyEntry.getType();
|
||||||
if ( sourceType.isPrimitive() && !targetType.isPrimitive() ) {
|
if ( sourceType.isPrimitive() && !targetType.isPrimitive() ) {
|
||||||
// Handle null's. If the forged method needs to be mapped to an object, the forged method must be
|
// Handle null's. If the forged method needs to be mapped to an object, the forged method must be
|
||||||
// able to return null. So in that case primitive types are mapped to their corresponding wrapped
|
// able to return null. So in that case primitive types are mapped to their corresponding wrapped
|
||||||
@ -581,7 +578,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// create a local variable to which forged method can be assigned.
|
// create a local variable to which forged method can be assigned.
|
||||||
String desiredName = last( sourceReference.getPropertyEntries() ).getName();
|
String desiredName = propertyEntry.getName();
|
||||||
sourceRhs.setSourceLocalVarName( sourceRhs.createUniqueVarName( desiredName ) );
|
sourceRhs.setSourceLocalVarName( sourceRhs.createUniqueVarName( desiredName ) );
|
||||||
|
|
||||||
return sourceRhs;
|
return sourceRhs;
|
||||||
@ -595,7 +592,7 @@ public class PropertyMapping extends ModelElement {
|
|||||||
Parameter sourceParam = sourceReference.getParameter();
|
Parameter sourceParam = sourceReference.getParameter();
|
||||||
// TODO is first correct here?? shouldn't it be last since the remainer is checked
|
// TODO is first correct here?? shouldn't it be last since the remainer is checked
|
||||||
// in the forged method?
|
// in the forged method?
|
||||||
PropertyEntry propertyEntry = first( sourceReference.getPropertyEntries() );
|
PropertyEntry propertyEntry = sourceReference.getShallowestProperty();
|
||||||
if ( propertyEntry.getPresenceChecker() != null ) {
|
if ( propertyEntry.getPresenceChecker() != null ) {
|
||||||
sourcePresenceChecker = sourceParam.getName()
|
sourcePresenceChecker = sourceParam.getName()
|
||||||
+ "." + propertyEntry.getPresenceChecker().getSimpleName() + "()";
|
+ "." + propertyEntry.getPresenceChecker().getSimpleName() + "()";
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 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.beanmapping;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.internal.model.common.Parameter;
|
||||||
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
|
|
||||||
|
import static org.mapstruct.ap.internal.util.Collections.first;
|
||||||
|
import static org.mapstruct.ap.internal.util.Collections.last;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class acts as a common base class for {@link TargetReference} and {@link SourceReference}.
|
||||||
|
*
|
||||||
|
* @author sjaak
|
||||||
|
*/
|
||||||
|
public abstract class AbstractReference {
|
||||||
|
|
||||||
|
private final Parameter parameter;
|
||||||
|
private final List<PropertyEntry> propertyEntries;
|
||||||
|
private final boolean isValid;
|
||||||
|
|
||||||
|
protected AbstractReference(Parameter sourceParameter, List<PropertyEntry> sourcePropertyEntries, boolean isValid) {
|
||||||
|
this.parameter = sourceParameter;
|
||||||
|
this.propertyEntries = sourcePropertyEntries;
|
||||||
|
this.isValid = isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parameter getParameter() {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PropertyEntry> getPropertyEntries() {
|
||||||
|
return propertyEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getElementNames() {
|
||||||
|
List<String> elementNames = new ArrayList<>();
|
||||||
|
if ( parameter != null ) {
|
||||||
|
// only relevant for source properties
|
||||||
|
elementNames.add( parameter.getName() );
|
||||||
|
}
|
||||||
|
for ( PropertyEntry propertyEntry : propertyEntries ) {
|
||||||
|
elementNames.add( propertyEntry.getName() );
|
||||||
|
}
|
||||||
|
return elementNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the property name on the shallowest nesting level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PropertyEntry getShallowestProperty() {
|
||||||
|
if ( propertyEntries.isEmpty() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return first( propertyEntries );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the property name on the shallowest nesting level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getShallowestPropertyName() {
|
||||||
|
if ( propertyEntries.isEmpty() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return first( propertyEntries ).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the property name on the deepest nesting level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PropertyEntry getDeepestProperty() {
|
||||||
|
if ( propertyEntries.isEmpty() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return last( propertyEntries );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the property name on the deepest nesting level
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getDeepestPropertyName() {
|
||||||
|
if ( propertyEntries.isEmpty() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return last( propertyEntries ).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNested() {
|
||||||
|
return propertyEntries.size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
if ( !isValid ) {
|
||||||
|
result = "invalid";
|
||||||
|
}
|
||||||
|
else if ( propertyEntries.isEmpty() ) {
|
||||||
|
if ( parameter != null ) {
|
||||||
|
result = String.format( "parameter \"%s %s\"", parameter.getType(), parameter.getName() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( propertyEntries.size() == 1 ) {
|
||||||
|
PropertyEntry propertyEntry = propertyEntries.get( 0 );
|
||||||
|
result = String.format( "property \"%s %s\"", propertyEntry.getType(), propertyEntry.getName() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PropertyEntry lastPropertyEntry = propertyEntries.get( propertyEntries.size() - 1 );
|
||||||
|
result = String.format(
|
||||||
|
"property \"%s %s\"",
|
||||||
|
lastPropertyEntry.getType(),
|
||||||
|
Strings.join( getElementNames(), "." )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,6 @@ package org.mapstruct.ap.internal.model.beanmapping;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.mapstruct.ap.internal.model.source.Mapping;
|
import org.mapstruct.ap.internal.model.source.Mapping;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the intermediate (nesting) state of the {@link Mapping} in this class.
|
* Represents the intermediate (nesting) state of the {@link Mapping} in this class.
|
||||||
@ -80,16 +79,24 @@ public class MappingReference {
|
|||||||
return Objects.hash( mapping );
|
return Objects.hash( mapping );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isValid( ) {
|
||||||
|
boolean result = false;
|
||||||
|
if ( targetReference.isValid() ) {
|
||||||
|
result = sourceReference != null ? sourceReference.isValid() : true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String targetRefName = Strings.join( targetReference.getElementNames(), "." );
|
String targetRefStr = targetReference.toString();
|
||||||
String sourceRefName = "null";
|
String sourceRefStr = "null";
|
||||||
if ( sourceReference != null ) {
|
if ( sourceReference != null ) {
|
||||||
sourceRefName = Strings.join( sourceReference.getElementNames(), "." );
|
sourceRefStr = sourceReference.toString();
|
||||||
}
|
}
|
||||||
return "MappingReference {"
|
return "MappingReference {"
|
||||||
+ "\n sourceRefName='" + sourceRefName + "\',"
|
+ "\n sourceReference='" + sourceRefStr + "\',"
|
||||||
+ "\n targetRefName='" + targetRefName + "\',"
|
+ "\n targetReference='" + targetRefStr + "\',"
|
||||||
+ "\n}";
|
+ "\n}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,9 @@ public class MappingReferences {
|
|||||||
public static MappingReferences forSourceMethod(SourceMethod sourceMethod, FormattingMessager messager,
|
public static MappingReferences forSourceMethod(SourceMethod sourceMethod, FormattingMessager messager,
|
||||||
TypeFactory typeFactory) {
|
TypeFactory typeFactory) {
|
||||||
|
|
||||||
Set<Mapping> mappings = sourceMethod.getMappingOptions().getMappings();
|
|
||||||
|
|
||||||
|
|
||||||
Set<MappingReference> references = new LinkedHashSet<>();
|
Set<MappingReference> references = new LinkedHashSet<>();
|
||||||
|
Set<MappingReference> targetThisReferences = new LinkedHashSet<>();
|
||||||
|
|
||||||
for ( Mapping mapping : sourceMethod.getMappingOptions().getMappings() ) {
|
for ( Mapping mapping : sourceMethod.getMappingOptions().getMappings() ) {
|
||||||
|
|
||||||
// handle source reference
|
// handle source reference
|
||||||
@ -52,9 +51,15 @@ public class MappingReferences {
|
|||||||
// add when inverse is also valid
|
// add when inverse is also valid
|
||||||
MappingReference mappingReference = new MappingReference( mapping, targetReference, sourceReference );
|
MappingReference mappingReference = new MappingReference( mapping, targetReference, sourceReference );
|
||||||
if ( isValidWhenInversed( mappingReference ) ) {
|
if ( isValidWhenInversed( mappingReference ) ) {
|
||||||
references.add( mappingReference );
|
if ( targetReference.isTargetThis() ) {
|
||||||
|
targetThisReferences.add( mappingReference );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
references.add( mappingReference );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
references.addAll( targetThisReferences );
|
||||||
return new MappingReferences( references, false );
|
return new MappingReferences( references, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +109,7 @@ public class MappingReferences {
|
|||||||
|
|
||||||
for ( MappingReference mappingRef : mappingReferences ) {
|
for ( MappingReference mappingRef : mappingReferences ) {
|
||||||
TargetReference targetReference = mappingRef.getTargetReference();
|
TargetReference targetReference = mappingRef.getTargetReference();
|
||||||
if ( targetReference.isValid() && targetReference.getPropertyEntries().size() > 1 ) {
|
if ( targetReference.isValid() && targetReference.isNested()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
package org.mapstruct.ap.internal.model.beanmapping;
|
package org.mapstruct.ap.internal.model.beanmapping;
|
||||||
|
|
||||||
import static org.mapstruct.ap.internal.model.beanmapping.PropertyEntry.forSourceReference;
|
import static org.mapstruct.ap.internal.model.beanmapping.PropertyEntry.forSourceReference;
|
||||||
import static org.mapstruct.ap.internal.util.Collections.first;
|
|
||||||
import static org.mapstruct.ap.internal.util.Collections.last;
|
import static org.mapstruct.ap.internal.util.Collections.last;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -22,7 +21,6 @@ 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.Mapping;
|
import org.mapstruct.ap.internal.model.source.Mapping;
|
||||||
import org.mapstruct.ap.internal.model.source.Method;
|
import org.mapstruct.ap.internal.model.source.Method;
|
||||||
import org.mapstruct.ap.internal.model.source.SourceMethod;
|
|
||||||
import org.mapstruct.ap.internal.util.FormattingMessager;
|
import org.mapstruct.ap.internal.util.FormattingMessager;
|
||||||
import org.mapstruct.ap.internal.util.Message;
|
import org.mapstruct.ap.internal.util.Message;
|
||||||
import org.mapstruct.ap.internal.util.Strings;
|
import org.mapstruct.ap.internal.util.Strings;
|
||||||
@ -50,11 +48,7 @@ import org.mapstruct.ap.internal.util.accessor.Accessor;
|
|||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class SourceReference {
|
public class SourceReference extends AbstractReference {
|
||||||
|
|
||||||
private final Parameter parameter;
|
|
||||||
private final List<PropertyEntry> propertyEntries;
|
|
||||||
private final boolean isValid;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a {@link SourceReference} from an {@code @Mappping}.
|
* Builds a {@link SourceReference} from an {@code @Mappping}.
|
||||||
@ -371,88 +365,23 @@ public class SourceReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SourceReference build() {
|
public SourceReference build() {
|
||||||
return new SourceReference( sourceParameter, sourceReference.propertyEntries, true );
|
return new SourceReference( sourceParameter, sourceReference.getPropertyEntries(), true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceReference(Parameter sourceParameter, List<PropertyEntry> sourcePropertyEntries, boolean isValid) {
|
private SourceReference(Parameter sourceParameter, List<PropertyEntry> sourcePropertyEntries, boolean isValid) {
|
||||||
this.parameter = sourceParameter;
|
super( sourceParameter, sourcePropertyEntries, isValid );
|
||||||
this.propertyEntries = sourcePropertyEntries;
|
|
||||||
this.isValid = isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Parameter getParameter() {
|
|
||||||
return parameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<PropertyEntry> getPropertyEntries() {
|
|
||||||
return propertyEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getElementNames() {
|
|
||||||
List<String> sourceName = new ArrayList<>();
|
|
||||||
sourceName.add( parameter.getName() );
|
|
||||||
for ( PropertyEntry propertyEntry : propertyEntries ) {
|
|
||||||
sourceName.add( propertyEntry.getName() );
|
|
||||||
}
|
|
||||||
return sourceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a copy of this reference, which is adapted to the given method
|
|
||||||
*
|
|
||||||
* @param method the method to create the copy for
|
|
||||||
* @return the copy
|
|
||||||
*/
|
|
||||||
public SourceReference copyForInheritanceTo(SourceMethod method) {
|
|
||||||
List<Parameter> replacementParamCandidates = new ArrayList<>();
|
|
||||||
for ( Parameter sourceParam : method.getSourceParameters() ) {
|
|
||||||
if ( parameter != null && sourceParam.getType().isAssignableTo( parameter.getType() ) ) {
|
|
||||||
replacementParamCandidates.add( sourceParam );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Parameter replacement = parameter;
|
|
||||||
if ( replacementParamCandidates.size() == 1 ) {
|
|
||||||
replacement = first( replacementParamCandidates );
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SourceReference( replacement, propertyEntries, isValid );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceReference pop() {
|
public SourceReference pop() {
|
||||||
if ( propertyEntries.size() > 1 ) {
|
if ( getPropertyEntries().size() > 1 ) {
|
||||||
List<PropertyEntry> newPropertyEntries =
|
List<PropertyEntry> newPropertyEntries =
|
||||||
new ArrayList<>( propertyEntries.subList( 1, propertyEntries.size() ) );
|
new ArrayList<>( getPropertyEntries().subList( 1, getPropertyEntries().size() ) );
|
||||||
return new SourceReference( parameter, newPropertyEntries, isValid );
|
return new SourceReference( getParameter(), newPropertyEntries, isValid() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
|
|
||||||
if ( propertyEntries.isEmpty() ) {
|
|
||||||
return String.format( "parameter \"%s %s\"", getParameter().getType(), getParameter().getName() );
|
|
||||||
}
|
|
||||||
else if ( propertyEntries.size() == 1 ) {
|
|
||||||
PropertyEntry propertyEntry = propertyEntries.get( 0 );
|
|
||||||
return String.format( "property \"%s %s\"", propertyEntry.getType(), propertyEntry.getName() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PropertyEntry lastPropertyEntry = propertyEntries.get( propertyEntries.size() - 1 );
|
|
||||||
return String.format(
|
|
||||||
"property \"%s %s\"",
|
|
||||||
lastPropertyEntry.getType(),
|
|
||||||
Strings.join( getElementNames(), "." )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,7 @@ import static org.mapstruct.ap.internal.util.Collections.first;
|
|||||||
*
|
*
|
||||||
* @author Sjaak Derksen
|
* @author Sjaak Derksen
|
||||||
*/
|
*/
|
||||||
public class TargetReference {
|
public class TargetReference extends AbstractReference {
|
||||||
|
|
||||||
private final Parameter parameter;
|
|
||||||
private final List<PropertyEntry> propertyEntries;
|
|
||||||
private final boolean isValid;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a {@link TargetReference} from an {@code @Mappping}.
|
* Builds a {@link TargetReference} from an {@code @Mappping}.
|
||||||
@ -348,46 +343,24 @@ public class TargetReference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private TargetReference(Parameter sourceParameter, List<PropertyEntry> sourcePropertyEntries, boolean isValid) {
|
private TargetReference(Parameter sourceParameter, List<PropertyEntry> targetPropertyEntries, boolean isValid) {
|
||||||
this.parameter = sourceParameter;
|
super( sourceParameter, targetPropertyEntries, isValid );
|
||||||
this.propertyEntries = sourcePropertyEntries;
|
|
||||||
this.isValid = isValid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Parameter getParameter() {
|
public boolean isTargetThis() {
|
||||||
return parameter;
|
return getPropertyEntries().isEmpty();
|
||||||
}
|
|
||||||
|
|
||||||
public List<PropertyEntry> getPropertyEntries() {
|
|
||||||
return propertyEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getElementNames() {
|
|
||||||
List<String> elementNames = new ArrayList<>();
|
|
||||||
if ( parameter != null ) {
|
|
||||||
// only relevant for source properties
|
|
||||||
elementNames.add( parameter.getName() );
|
|
||||||
}
|
|
||||||
for ( PropertyEntry propertyEntry : propertyEntries ) {
|
|
||||||
elementNames.add( propertyEntry.getName() );
|
|
||||||
}
|
|
||||||
return elementNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TargetReference pop() {
|
public TargetReference pop() {
|
||||||
if ( propertyEntries.size() > 1 ) {
|
if ( getPropertyEntries().size() > 1 ) {
|
||||||
List<PropertyEntry> newPropertyEntries = new ArrayList<>( propertyEntries.size() - 1 );
|
List<PropertyEntry> newPropertyEntries = new ArrayList<>( getPropertyEntries().size() - 1 );
|
||||||
for ( PropertyEntry propertyEntry : propertyEntries ) {
|
for ( PropertyEntry propertyEntry : getPropertyEntries() ) {
|
||||||
PropertyEntry newPropertyEntry = propertyEntry.pop();
|
PropertyEntry newPropertyEntry = propertyEntry.pop();
|
||||||
if ( newPropertyEntry != null ) {
|
if ( newPropertyEntry != null ) {
|
||||||
newPropertyEntries.add( newPropertyEntry );
|
newPropertyEntries.add( newPropertyEntry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new TargetReference( null, newPropertyEntries, isValid );
|
return new TargetReference( null, newPropertyEntries, isValid() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -63,8 +63,8 @@ public class OrderingTest {
|
|||||||
@Diagnostic(type = ErroneousAddressMapperWithCyclicDependency.class,
|
@Diagnostic(type = ErroneousAddressMapperWithCyclicDependency.class,
|
||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
line = 24,
|
line = 24,
|
||||||
messageRegExp = "Cycle\\(s\\) between properties given via dependsOn\\(\\): firstName -> lastName -> "
|
messageRegExp = "Cycle\\(s\\) between properties given via dependsOn\\(\\): lastName -> middleName -> "
|
||||||
+ "middleName -> firstName"
|
+ "firstName -> lastName"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -84,11 +84,11 @@ public class SuggestMostSimilarNameTest {
|
|||||||
diagnostics = {
|
diagnostics = {
|
||||||
@Diagnostic(type = PersonGarageWrongSourceMapper.class,
|
@Diagnostic(type = PersonGarageWrongSourceMapper.class,
|
||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
line = 19,
|
line = 21,
|
||||||
messageRegExp = "No property named \"garage\\.colour\\.rgb\".*Did you mean \"garage\\.color\"\\?"),
|
messageRegExp = "No property named \"garage\\.colour\\.rgb\".*Did you mean \"garage\\.color\"\\?"),
|
||||||
@Diagnostic(type = PersonGarageWrongSourceMapper.class,
|
@Diagnostic(type = PersonGarageWrongSourceMapper.class,
|
||||||
kind = javax.tools.Diagnostic.Kind.ERROR,
|
kind = javax.tools.Diagnostic.Kind.ERROR,
|
||||||
line = 22,
|
line = 28,
|
||||||
messageRegExp = "No property named \"garage\\.colour\".*Did you mean \"garage\\.color\"\\?")
|
messageRegExp = "No property named \"garage\\.colour\".*Did you mean \"garage\\.color\"\\?")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ package org.mapstruct.ap.test.namesuggestion.erroneous;
|
|||||||
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mapping;
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.ap.test.namesuggestion.Person;
|
import org.mapstruct.ap.test.namesuggestion.Person;
|
||||||
import org.mapstruct.ap.test.namesuggestion.PersonDto;
|
import org.mapstruct.ap.test.namesuggestion.PersonDto;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -16,10 +17,18 @@ public interface PersonGarageWrongSourceMapper {
|
|||||||
|
|
||||||
PersonGarageWrongSourceMapper MAPPER = Mappers.getMapper( PersonGarageWrongSourceMapper.class );
|
PersonGarageWrongSourceMapper MAPPER = Mappers.getMapper( PersonGarageWrongSourceMapper.class );
|
||||||
|
|
||||||
@Mapping(source = "garage.colour.rgb", target = "garage.color.rgb")
|
@Mappings( {
|
||||||
|
@Mapping( target = "garage.color.rgb", source = "garage.colour.rgb" ),
|
||||||
|
@Mapping( target = "fullAge", source = "age" ),
|
||||||
|
@Mapping( target = "fullName", source = "name" )
|
||||||
|
} )
|
||||||
Person mapPerson(PersonDto dto);
|
Person mapPerson(PersonDto dto);
|
||||||
|
|
||||||
@Mapping(source = "garage.colour", target = "garage.color")
|
@Mappings( {
|
||||||
|
@Mapping( target = "garage.color", source = "garage.colour" ),
|
||||||
|
@Mapping( target = "fullAge", source = "age" ),
|
||||||
|
@Mapping( target = "fullName", source = "name" )
|
||||||
|
} )
|
||||||
Person mapPersonGarage(PersonDto dto);
|
Person mapPersonGarage(PersonDto dto);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user