Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ private Builder setupMethodWithMapping(Method sourceMethod) {
this.method = sourceMethod;
this.methodMappings = sourceMethod.getMappingOptions().getMappings();
CollectionMappingStrategyPrism cms = sourceMethod.getMapperConfiguration().getCollectionMappingStrategy();
Map<String, Accessor> accessors = method.getResultType().getPropertyWriteAccessors( cms );
Map<String, Accessor> srcReadAccessors = sourceMethod.getSourceReadAccessors();

Map<String, Accessor> accessors = method.getResultType().getPropertyWriteAccessors( cms,
( srcReadAccessors ) );

this.targetProperties = accessors.keySet();

this.unprocessedTargetProperties = new LinkedHashMap<String, Accessor>( accessors );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.lang.model.element.ExecutableElement;
Expand All @@ -34,6 +35,7 @@
import org.mapstruct.ap.internal.model.source.ParameterProvidedMethods;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Strings;
import org.mapstruct.ap.internal.util.accessor.Accessor;

/**
* A non mapping method to be generated.
Expand Down Expand Up @@ -265,4 +267,8 @@ public boolean isLifecycleCallbackMethod() {
public boolean isUpdateMethod() {
return false; // irrelevant
}

public Map<String, Accessor> getSourceReadAccessors() {
return Collections.emptyMap();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,11 @@ public Map<String, ExecutableElementAccessor> getPropertyPresenceCheckers() {
return presenceCheckers;
}

public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) {
return getPropertyWriteAccessors( cmStrategy, Collections.<String, Accessor>emptyMap() );
}


/**
* getPropertyWriteAccessors returns a map of the write accessors according to the CollectionMappingStrategy. These
* accessors include:
Expand All @@ -450,7 +455,8 @@ public Map<String, ExecutableElementAccessor> getPropertyPresenceCheckers() {
* @param cmStrategy collection mapping strategy
* @return an unmodifiable map of all write accessors indexed by property name
*/
public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy ) {
public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrategyPrism cmStrategy,
Map<String, Accessor> sourceAccessor ) {
// collect all candidate target accessors
List<Accessor> candidates = new ArrayList<Accessor>( getSetters() );
candidates.addAll( getAlternativeTargetAccessors() );
Expand All @@ -461,8 +467,8 @@ public Map<String, Accessor> getPropertyWriteAccessors( CollectionMappingStrateg
String targetPropertyName = Executables.getPropertyName( candidate );

Accessor readAccessor = getPropertyReadAccessors().get( targetPropertyName );

Type preferredType = determinePreferredType( readAccessor );
Accessor sourceReadAccessor = sourceAccessor.get( targetPropertyName );
TypeMirror preferredType = determinePreferredType( readAccessor, sourceReadAccessor );
Type targetType = determineTargetType( candidate );

// A target access is in general a setter method on the target object. However, in case of collections,
Expand Down Expand Up @@ -496,18 +502,60 @@ else if ( Executables.isFieldAccessor( candidate ) && ( Executables.isFinal( can
}

Accessor previousCandidate = result.get( targetPropertyName );
if ( previousCandidate == null || preferredType == null || ( targetType != null
&& typeUtils.isAssignable( preferredType.getTypeMirror(), targetType.getTypeMirror() ) ) ) {


if (previousCandidate != null
&& sourceAccessor != null
&& sourceReadAccessor != null
&& !isBetter( previousCandidate, candidate,
sourceReadAccessor.getAccessedType() ) ) {
continue;
}


if (previousCandidate == null || preferredType == null || (targetType != null
&& typeUtils.isAssignable( preferredType, targetType.getTypeMirror() ) ) ) {
result.put( targetPropertyName, candidate );
}
}

return result;
}

private Type determinePreferredType(Accessor readAccessor) {
private TypeMirror extractTypeMirror( Accessor accessor ) {
if ( accessor.getExecutable() == null ) {
return null;
}
return accessor.getExecutable().getParameters().get( 0 ).asType();
}

private boolean isBetter( Accessor previousCandidate, Accessor nextCandidate, TypeMirror preferredType ) {
TypeMirror previousType = extractTypeMirror( previousCandidate );
TypeMirror nextType = extractTypeMirror( nextCandidate );
if ( nextType == null ) {
return false;
}

if (typeUtils.isSameType( previousType, preferredType )) {
return false;
}

if (typeUtils.isSameType( nextType, preferredType )) {
return true;
}
if (typeUtils.isAssignable( nextType, preferredType )
&& !typeUtils.isAssignable( previousType, preferredType )) {
return true;
}
return false;
}

private TypeMirror determinePreferredType(Accessor readAccessor, Accessor sourceReadAccessor) {
if ( sourceReadAccessor != null ) {
return sourceReadAccessor.getAccessedType();
}
if ( readAccessor != null ) {
return typeFactory.getReturnType( (DeclaredType) typeMirror, readAccessor );
return typeFactory.getReturnType( (DeclaredType) typeMirror, readAccessor ).getTypeMirror();
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.lang.model.element.ExecutableElement;

Expand All @@ -29,6 +30,7 @@
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.Strings;
import org.mapstruct.ap.internal.util.accessor.Accessor;

/**
* This method will be generated in absence of a suitable abstract method to implement.
Expand All @@ -51,6 +53,7 @@ public class ForgedMethod implements Method {
private final MappingOptions mappingOptions;
private final ParameterProvidedMethods contextProvidedMethods;
private final boolean forgedNameBased;
private final Map<String, Accessor> sourceReadAccessors;

/**
* Creates a new forged method with the given name.
Expand Down Expand Up @@ -120,6 +123,7 @@ public ForgedMethod(String name, Type sourceType, Type returnType, MapperConfigu
this.mappingOptions = mappingOptions == null ? MappingOptions.empty() : mappingOptions;
this.mappingOptions.initWithParameter( sourceParameter );
this.forgedNameBased = forgedNameBased;
this.sourceReadAccessors = MappingMethodUtils.getSourceReadAccessors( getSourceParameters(), mappingOptions );
}

/**
Expand All @@ -143,6 +147,7 @@ public ForgedMethod(String name, ForgedMethod forgedMethod) {

this.name = name;
this.forgedNameBased = forgedMethod.forgedNameBased;
this.sourceReadAccessors = forgedMethod.sourceReadAccessors;
}

@Override
Expand Down Expand Up @@ -321,6 +326,10 @@ public MappingOptions getMappingOptions() {
return mappingOptions;
}

public Map<String, Accessor> getSourceReadAccessors() {
return sourceReadAccessors;
}

@Override
public boolean equals(Object o) {
if ( this == o ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ public List<String> getDependsOn() {

private boolean hasPropertyInReverseMethod(String name, SourceMethod method) {
CollectionMappingStrategyPrism cms = method.getMapperConfiguration().getCollectionMappingStrategy();
return method.getResultType().getPropertyWriteAccessors( cms ).containsKey( name );
return method.getResultType().getPropertyWriteAccessors( cms, method.getSourceReadAccessors() )
.containsKey( name );
}

public Mapping reverse(SourceMethod method, FormattingMessager messager, TypeFactory typeFactory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
*/
package org.mapstruct.ap.internal.model.source;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.mapstruct.ap.internal.model.common.Parameter;
import org.mapstruct.ap.internal.util.accessor.Accessor;

import static org.mapstruct.ap.internal.util.Collections.first;

/**
Expand Down Expand Up @@ -45,4 +53,33 @@ public static boolean isEnumMapping(Method method) {
&& first( method.getSourceParameters() ).getType().isEnumType()
&& method.getResultType().isEnumType();
}

public static Map<String, Accessor> getSourceReadAccessors(List<Parameter> sourceParameters,
MappingOptions mappingOptions) {

if ( mappingOptions == null ) {
return Collections.emptyMap();
}

Map<String, Accessor> map = new LinkedHashMap<String, Accessor>();
Map<String, String> bindings = new LinkedHashMap<String, String>();
if ( mappingOptions.getMappings() != null ) {
for ( Map.Entry<String, List<Mapping>> entry : mappingOptions.getMappings().entrySet() ) {
if ( entry.getValue() != null && entry.getValue().size() > 0 ) {
bindings.put( entry.getKey(), entry.getValue().get( 0 ).getSourceName() );
}
}
}

for ( Parameter parameter : sourceParameters ) {
map.putAll( parameter.getType().getPropertyReadAccessors() );
}

for ( Map.Entry<String, String> entry : bindings.entrySet() ) {
if ( map.get( entry.getValue() ) != null ) {
map.put( entry.getKey(), map.remove( entry.getValue() ) );
}
}
return Collections.unmodifiableMap( map );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.mapstruct.ap.internal.model.source;

import java.util.List;
import java.util.Map;

import javax.lang.model.element.ExecutableElement;

Expand All @@ -27,6 +28,7 @@
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.source.builtin.BuiltInMethod;
import org.mapstruct.ap.internal.util.MapperConfiguration;
import org.mapstruct.ap.internal.util.accessor.Accessor;

/**
* This interface makes available common method properties and a matching method There are 2 known implementors:
Expand Down Expand Up @@ -200,4 +202,11 @@ public interface Method {
* @return the mapping options for this method
*/
MappingOptions getMappingOptions();

/**
*
* @return map of possible accessors
*/

Map<String, Accessor> getSourceReadAccessors();
}
Loading