Streams in ModelMapper?

599 views
Skip to first unread message

Ernesto Diaz

unread,
Jul 11, 2017, 11:35:29 AM7/11/17
to modelmapper
Hi,

Now we have lots of mappings between 2 lists of different type of objects. At the moment we are solving it by creating a Converter that gets both lists and then solves the mapping using Java 8 streaming (inside).

Probably, it would be more elegant streaming inside the mapping definition using a much simpler converter between the source and the destination object (not between their lists). Probably creating the destination in case of an empty list.

Is it something we can do at the moment? If not, is it under the road map?

Thank you in advance,
Ernesto


Chun Han Hsiao

unread,
Jul 14, 2017, 7:51:01 PM7/14/17
to modelmapper
Hi,

Can you provide some example for your source type and destination type ?
I guess for your case is that your source type contains a field with type List<BaseSrc>, and you want to map the source type to destination type contains a field with type List<BaseDest> . And the BaseSrc and the BaseDest contains many different Sub-Class or implementation.
Is that match to your case ? I think it will be great to have the example so that I can fully understand for your case and give you suggestion or improved the ModelMapper API to fulfill your use case. Thanks!

Ernesto Diaz於 2017年7月11日星期二 UTC+8下午11時35分29秒寫道:
Message has been deleted

Ernesto Diaz

unread,
Jul 20, 2017, 9:21:55 AM7/20/17
to modelmapper
Hi,

Thank you for your response. I will try to explain a bit better what I was trying to ask from you with some piece of codes. Basically we have our own data structure and we have to fulfill a standard protocol with this data. In several places we have mappings like this one:

                using(new CountryOfOriginsToSPSConsignmentItemTypeListConverter()).map(source.getCoiExtractTranslation()
                                                                                             .getCountryOfOrigins(),
                                                                                       destination.getTotalSPSTradeLineItemType()
                                                                                                  .getOriginSPSCountry());
Then countryOfOrigins is a list of CountryTranslation objects
public class CountryTranslation implements....{
      private String countryName;
      private String countryCode;
              ...........
      //getters + setters
}
On the other hand the originSPSCountry (a standard protocol we got where a list is wrongly called in singular...) is based on a list of SPSCountryType:
public class SPSCountryType {
    protected IDType id;
    protected List<TextType> name;
                ....
    //getters + setters
}
Now:
The converter takes 2 lists and iterates them this way:
public class CountryOfOriginsToSPSConsignmentItemTypeListConverter implements SourceTranslatableConverter<List<CountryTranslation>, List<SPSCountryType>> {

    @Override
    public List<SPSCountryType> convert(MappingContext<List<CountryTranslation>, List<SPSCountryType>> context) {
        List<CountryTranslation> sourceCountries = context.getSource();

        LanguageCode languageCode = extractLanguageCode(context);

        return sourceCountries.stream()
                              .map(c -> UncefactFactory.createSPSCountryType(c.getCode(), c.getTranslation(), languageCode.getCode()))
                              .collect(Collectors.toList());

    }
}

Probably a more clean solution:
We were thinking that it would be more clear for us if we would use Java 8 streaming inside the config definition, (somehow) having a converter that just maps the iterated CountryTranslation into SPSCountryType objects and not a full ListCountryTranslation> into a full List<SPSCountryType>.
A difficult point would be whether the destination list is empty or not, whether to update or create a list item. In our case creation would be enough as we are just orchestrating 2 protocols, but generally speaking their content, equals, comparators could be used to identify whether to update or create...
So, basically these are our thoughts, mainly starting from our use cases. Then we can use the advantages of the mapping declaration having our code free of ugly if statements.
I am wondering about your opinion.
Thank you in advance!
Ernesto
(by the way we have places where we have to map a list that is inside of an item, which is inside another list, but I will post it after your opinion)

Chun Han Hsiao

unread,
Jul 21, 2017, 10:14:12 PM7/21/17
to modelmapper
Hi,

Thanks for the detailed explanation. For your case, I think you can just add CountryOfOriginsToSPSConsignmentItemTypeListConverter into ModelMapper.
modelMapper.addConverter(new CountryOfOriginsToSPSConsignmentItemTypeListConverter());

Second, define your explicit mapping without using converter
map(source.getCoiExtractTranslation().getCountryOfOrigins(),
    destination.getTotalSPSTradeLineItemType().getOriginSPSCountry());

Hope this will solve your problem!

Regards,
Chun Han

Ernesto Diaz於 2017年7月20日星期四 UTC+8下午9時21分55秒寫道:

Ernesto Diaz

unread,
Aug 1, 2017, 4:35:48 AM8/1/17
to modelmapper
Hi,

Thank you for your answer!
First of all, sorry for my late response, I was on holidays and I have just returned back to work. 
I would like to ask something before starting doing any coding, because the code is huge.. :). Are you proposing to change:

public class CountryOfOriginsToSPSConsignmentItemTypeListConverter implements SourceTranslatableConverter<List<CountryTranslation>, List<SPSCountryType>> {
   ......
}
to:
public class CountryOfOriginsToSPSConsignmentItemTypeListConverter implements SourceTranslatableConverter<CountryTranslationSPSCountryType> {
    .....
}
and then change the code the way you suggested below? 
Basically, changing the mapper definition from a list to a simple object definition, then adding this converter to the mapper and then defining the mapping at the list level.
This way the ModelMapper will take the list elements, one by one (recognizing the types that are inside the list), iterating and mapping them and creating a new object in the destination if required?

Thank you in advance!
Ernesto

Chun Han Hsiao

unread,
Aug 7, 2017, 7:18:49 PM8/7/17
to modelmapper
Hi Ernesto,

Yes, that's the behavior of modelmapper.

Regards,
Chun Han Hsiao

Ernesto Diaz於 2017年8月1日星期二 UTC+8下午4時35分48秒寫道:

Ernesto Diaz

unread,
Aug 8, 2017, 3:33:05 AM8/8/17
to modelmapper
Hi Chun,

Thank you for your feedback! Perfect, it was my mistake then. I am going to test it now, thanks!!
Ernesto

Ernesto Diaz

unread,
Aug 9, 2017, 5:23:59 AM8/9/17
to modelmapper
Hi Chun,

It works perfectly, many thanks!!
Ernesto
Reply all
Reply to author
Forward
0 new messages