Skip to content

Group nested source mappings #1048

@filiphr

Description

@filiphr

Instead of generating a new method for each mapping we might use something similar as in #1046 and use update mapping internally. For example for the mapping:

@Mapper
public interface ArtistToChartEntry {

    @Mappings({
        @Mapping(target = "chartName", ignore = true),
        @Mapping(target = "songTitle", source = "title"),
        @Mapping(target = "artistName", source = "artist.name"),
        @Mapping(target = "recordedAt", source = "artist.label.studio.name"),
        @Mapping(target = "city", source = "artist.label.studio.city"),
        @Mapping(target = "position", ignore = true)
    })
    ChartEntry map(Song song);
}

We generate:

public class ChartEntryToArtistImpl extends ChartEntryToArtist {

    @Override
    public ChartEntry map(Song song) {
        if ( song == null ) {
            return null;
        }

        ChartEntry chartEntry = new ChartEntry();

        chartEntry.setSongTitle( song.getTitle() );
        String city = songArtistLabelStudioCity1( song );
        if ( city != null ) {
            chartEntry.setCity( city );
        }
        String name = songArtistLabelStudioName1( song );
        if ( name != null ) {
            chartEntry.setRecordedAt( name );
        }
        String name1 = songArtistName1( song );
        if ( name1 != null ) {
            chartEntry.setArtistName( name1 );
        }

        return chartEntry;
    }

    private String songArtistLabelStudioCity1(Song song) {

        if ( song == null ) {
            return null;
        }
        Artist artist = song.getArtist();
        if ( artist == null ) {
            return null;
        }
        Label label = artist.getLabel();
        if ( label == null ) {
            return null;
        }
        Studio studio = label.getStudio();
        if ( studio == null ) {
            return null;
        }
        String city = studio.getCity();
        if ( city == null ) {
            return null;
        }
        return city;
    }

    private String songArtistLabelStudioName1(Song song) {

        if ( song == null ) {
            return null;
        }
        Artist artist = song.getArtist();
        if ( artist == null ) {
            return null;
        }
        Label label = artist.getLabel();
        if ( label == null ) {
            return null;
        }
        Studio studio = label.getStudio();
        if ( studio == null ) {
            return null;
        }
        String name = studio.getName();
        if ( name == null ) {
            return null;
        }
        return name;
    }

    private String songArtistName1(Song song) {

        if ( song == null ) {
            return null;
        }
        Artist artist = song.getArtist();
        if ( artist == null ) {
            return null;
        }
        String name = artist.getName();
        if ( name == null ) {
            return null;
        }
        return name;
    }
}

The methods songArtistLabelStudioCity1(Song song), songArtistLabelStudioName1(Song song), songArtistName1(Song song) have a lot of duplicated code.

What if we generate this instead:

public class ChartEntryToArtistImpl extends ChartEntryToArtist {

    @Override
    public ChartEntry map(Song song) {
        if ( song == null ) {
            return null;
        }

        ChartEntry chartEntry = new ChartEntry();

        chartEntry.setSongTitle( song.getTitle() );

        updateChartEntryFromArtist( chartEntry, song.getArtist() );

        return chartEntry;
    }

    private void updateChartEntryFromArtist(ChartEntry chartEntry, Artist artist) {
        if ( artist == null ) {
            return;
        }

        if ( artist.getName() != null ) {
            chartEntry.setArtistName( artist.getName() );
        }

        Label label = artist.getLabel();

        if ( label == null ) {
            return;
        }

        Studio studio = label.getStudio();

        if ( studio == null ) {
            return;
        }

        if ( studio.getName() != null ) {
            chartEntry.setRecordedAt( studio.getName() );
        }

        if ( studio.getCity() ) {
            chartEntry.setCity( studio.getCity() );
        }
    }
}

I think that with this the readability is much improved, we gain something small in performance (we don't need to repeat the same conditions multiple times) and we generate less code.

Do you think that this is worth pursuing?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions