Home > Software design >  Mapstruct - Mapping an object's list item with a method in a different mapper
Mapstruct - Mapping an object's list item with a method in a different mapper

Time:03-09

I have two mapper classes as below.


@Mapper
public interface CountryLanguageMapper {

    CountryLanguageMapper INSTANCE = Mappers.getMapper(CountryLanguageMapper.class);

    List<CountryLanguageResponse> toResponseList(List<CountryLanguage> source);

    @Mapping(target = "languageId", source = "id.language.id")
    CountryLanguageResponse toResponse(CountryLanguage source);

}


@Mapper
public interface CountryMapper {

    CountryMapper INSTANCE = Mappers.getMapper(CountryMapper.class);

    List<CountryListResponse> toResponseList(List<Country> source);

    @Mapping(target = "languages", source = "countryLanguages") // how should it be?
    CountryResponse toResponse(Country source);

    CountryListResponse toListResponse(Country source);

    @Mapping(target = "languages", source = "countryLanguages")
    CountryCreateResponse toCreateResponse(Country source);

    Country fromCreateRequest(CountryCreateRequest source);

    void updateFromUpdateRequest(CountryUpdateRequest source, @MappingTarget Country target);

}

Can I have the CountryMapper#toResponse method use the CountryLanguageMapper#toResponseList method when mapping the countryLanguages field?

If not possible how do I map "countryLanguages.id.language.id" to "languages.languageId" without writing a custom mapping method in CountryMapper?

Editing the CountryMapper class as follows works for me. But I was wondering if there is a way to use a method in different mapper.

@Mapper
public interface CountryMapper {

    CountryMapper INSTANCE = Mappers.getMapper(CountryMapper.class);

    List<CountryListResponse> toResponseList(List<Country> source);

    @Mapping(target = "languages", source = "countryLanguages", qualifiedByName = "toCountryLanguageResponseList")
    CountryResponse toResponse(Country source);

    CountryListResponse toListResponse(Country source);

    @Mapping(target = "languages", source = "countryLanguages")
    CountryCreateResponse toCreateResponse(Country source);

    @Mapping(target = "id", ignore = true)
    Country fromCreateRequest(CountryCreateRequest source);

    void updateFromUpdateRequest(CountryUpdateRequest source, @MappingTarget Country target);

    @IterableMapping(qualifiedByName = "toCountryLanguageResponse")
    @Named("toCountryLanguageResponseList")
    List<CountryLanguageResponse> toCountryLanguageResponseList(Collection<CountryLanguage> source);

    @Mapping(target = "languageId", source = "id.language.id")
    @Named("toCountryLanguageResponse")
    CountryLanguageResponse toCountryLanguageResponse(CountryLanguage source);

}

Thanks in advance :)

CodePudding user response:

this is possible with the uses directive.

for example:

@Mapper(uses=CountryLanguageMapper.class)
public interface CountryMapper {

for more information see here: https://mapstruct.org/documentation/dev/reference/html/#invoking-other-mappers

  • Related