#1148 Always add the generated MappingMethod if the MappingOptions are restricted to the defined mappings#1157
Conversation
|
You are right, the last property name or the source parameter name if there are no properties should be enough. The In the example the Maybe we can use the |
|
I think what you are explaining is in line with my suggestion in #1048. And yes using the By the way, you are commenting on my commit and not the PR :) |
|
Just as info, I have not squashed because @sjaakd comments are on my commit in my branch and I think that they would be lost if I force push. When merging it can be squashed into one commit :) |
|
So if I have two nested property mappings with different path-parts in the middle, this will still create two different methods? E.g. |
|
Thanks for the example @agudian. In your example we need to actually create 4 methods |
dc905fe to
1ac8749
Compare
|
@filiphr : I forgot why.. but why is it that we hand the complete source parameter instead of source properties in these scenarios? I'm not sure if that would matters simpler in all cases.. |
|
@sjaakd, sorry, but I don't quite understand what you mean. Can you maybe tell me where in the code I should look so I can understand it better? |
Well, consider the original problem: @Mapper
public interface MyMapper {
@Mappings({
@Mapping(source = "senderId", target = "sender.id"),
@Mapping(source = "recipientId", target = "recipient.id")
})
Entity toEntity(Dto dto);
}Now (prior to this PR) we create a mapping method: protected Client dtoToClient(Dto dto) {
if ( dto == null ) {
return null;
}
Client client = new Client();
client.setId( dto.getRecipientId() );
return client;
}But what if we would have generated the following protected Client stringToClient(String string) {
if ( dto == null ) {
return null;
}
Client client = new Client();
client.setId( string );
return client;
}So, when we cannot do symmetric stuff, we hand the source properties in stead of the source parameter.. The call site would then look something like this: public class MyMapperImpl implements MyMapper {
@Override
public Entity toEntity(Dto dto) {
if ( dto == null ) {
return null;
}
Entity entity = new Entity();
entity.setRecipient( stringToClient( dto.getRecepientId() ) );
entity.setSender( stringToClient( dto.getSenderId() ) );
return entity;
} |
|
Now I understand what you mean @sjaakd, thanks. You are saying that we do something similar to the |
I'll have a look and see if I can dig into this.. Not sure though whether I'll find some time 😄 |
|
@filiphr .. Did a first attempt... I ran into some issues.. First of all I changed the implementation on line 198 of if ( !groupedSourceReferences.nonNested.isEmpty() ) {
for ( Mapping mapping : groupedSourceReferences.nonNested ) {
MappingOptions nonNestedOptions = MappingOptions.forMappingsOnly(
groupByTargetName( groupedSourceReferences.nonNested ),
true
);
PropertyMapping propertyMapping = createPropertyMappingForNestedTarget(
nonNestedOptions,
targetProperty,
mapping.getSourceReference(),
forceUpdateMethod
);
if ( propertyMapping != null ) {
propertyMappings.add( propertyMapping );
}
handledTargets.add( entryByTP.getKey().getName() );
}
unprocessedDefinedTarget.put( targetProperty, groupedSourceReferences.notProcessedAppliesToAll );
}
}
}That fails on a an interesting line 642 in // if ( sourceType.isPrimitive() || targetType.isPrimitive() ) {
// return null;
// }The result is quite surprising. The call site of the implementation works as a charm: @Override
public Entity toEntity(Dto dto) {
if ( dto == null ) {
return null;
}
Entity entity = new Entity();
entity.setSender( longToClient( dto.senderId ) );
entity.client = clientDtoToClient( dto.sameLevel );
entity.client2 = clientDtoToClient( dto.sameLevel2 );
entity.nested2 = clientDtoToNestedClient( dto.level2 );
entity.nested = clientDtoToNestedClient( dto.level );
entity.setRecipient( longToClient1( dto.recipientId ) );
long id = dtoNestedDto2Id( dto );
entity.setId2( id );
long id1 = dtoNestedDtoId( dto );
entity.setId( id1 );
return entity;
}(note I did not remove your forcing part ye, hence however (of course I should say) MapStruct cannot (yet) generate a mapping from a primitive to a bean. protected Client longToClient(long long1) {
if ( ) {
return null;
}
Client client = new Client();
client.nestedClient = longToNestedClient( long1.senderId );
return client;
}So.. the question is now: is it a good idea to allow that and generate a proper mapping for such cases?? |
To answer that.. It seems that on the source side we do this already 😄 long id = dtoNestedDto2Id( dto );
entity.setId2( id ); |
|
The empty null check can be fixed by adding an additional check on line30 in
|
|
@sjaakd what if we generate something similar to the |
Thought about that as well. 2 reasons:
protected Client longToClient(long long1) {
Client client = new Client();
client.nestedClient = longToNestedClient( long1.senderId );
return client;
}
What's going wrong is that the In the mean time I wrote a new issue.. This |
|
Completely agree with you. How will this work when you have 2 properties that need to be non-nested mapped? Example: |
|
See the |
|
@sjaakd the things that you were trying out, do you have them locally or somehwere in your branches (I couldn't find them). I think that it will be good if we can wrap this one up so we can do the release |
|
I'll put them on a branch tonight.
Verstuurd vanaf mijn iPhone
… Op 17 mei 2017 om 22:47 heeft Filip Hrisafov ***@***.***> het volgende geschreven:
@sjaakd the things that you were trying out, do you have them locally or somehwere in your branches (I couldn't find them). I think that it will be good if we can wrap this one up so we can do the release
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
|
see #1203 .. |
|
@sjaakd I had a look at it and I also played around with it. We have the following problems: First of all we shouldn't generate this: protected Client stringToClient(String string) {
if ( dto == null ) {
return null;
}
Client client = new Client();
client.setId( string );
return client;
}But we should use update methods, because you can map multiple things into the client. This we can do and the generated code will look like: protected void stringToClient(String string, Client mappingTarget) {
if ( string == null ) {
return;
}
client.setId( string );
}And of course the caller will create the client like we do in an update method. I already managed to do this. However, there are some issues when the source reference is Also the What exactly don't you like with the current approach? |
I think we should. For 2 reasons..
This was my first thought as well. But now I don't think so. This would imply (in this case) that you have to pass multiple source parameters (and worse select them.). protected void stringToClient(String string, Long lng, Client mappingTarget) {
if ( string == null ) {
return;
}
// what about null checking long?
client.setId( string );
client.setLong( lng );
}Having said that, I think we need more time for this. Although this is a rather serious issue blocking a CR I would say. I also think we should fix #1197 first and then go back to this issue. When I started looking into this I got really confused by these constructs were you drag around mappings from multiple targets to multiple sources only for the sake of a deprecated enum mapping. We should re-map the old enum mapping asap to the new |
Are you talking about the
It is similar but not the same. For the target we shouldn't create a new object all the time. Let's take our We generate this method: protected FontDto letterEntityToFontDto(LetterEntity letterEntity) {
if ( letterEntity == null ) {
return null;
}
FontDto fontDto = new FontDto();
fontDto.setSize( letterEntity.getFontSize() );
fontDto.setType( letterEntity.getFontType() );
return fontDto;
}And we call it With the new proposal you are saying that we should call it like: letterDto.setFont( fontSizeToFontDto( entity.getFontSize() ) );
letterDto.setFont( fontTypeToFontDto( entity.getFont() ) );And we would generate will look like: protected FontDto fontSizeToFontDto(int fontSize) {
if ( fontSize== null ) {
return null;
}
FontDto fontDto = new FontDto();
fontDto.setSize( fontSize );
return fontDto;
}protected FontDto fontTypeToFontDto(String fontType) {
if ( fontType== null ) {
return null;
}
FontDto fontDto = new FontDto();
fontDto.setFontType( fontType);
return fontDto;
}Why I thought by using update methods is not like in your example, but for each of the If you don't have time for #1197 I can have a go at it. |
No.. I meant:
I don't think you're example is right.. In your example If there's no nesting anymore (no segments anymore) there's no more bean to map into.. The only thing you have to construct (and return) would be a |
The Maybe we need to schedule a call and/or talk on a chat to clarify this PR better. |
…ptions are restricted to the defined mappings
Fixes #1148.