2
votes

Suppose I need to map two objects into one or one object into one (overloading). I can do so with the following mapping:

@Mapper
public interface ThingMapper
{
    @Mappings(
        {
            @Mapping(source = "createdDateTime", target = "thingDate"),
            @Mapping(source = "approver.id", target = "approverId"),
        })
    ThingEventPayload toEventPayload(Thing thing);

    // TODO this is redundant, how to clean up?
    @Mappings(
        {
            // since there are two params, need to specifically map same-named params from source "thing" to target
            @Mapping(source = "thing.id", target = "id"),
            @Mapping(source = "thing.deletedDateTime", target = "deletedDateTime"),
            @Mapping(source = "thing.version", target = "version"),
            @Mapping(source = "thing.autoApproved", target = "autoApproved"),
            @Mapping(source = "thing.resolvedDate", target = "resolvedDate"),
            @Mapping(source = "thing.status", target = "status"),

            // numerous other fields mapping from source "thing" to target with same property name

            // map differently named parameters (duplicate of other mapper, above)
            @Mapping(source = "thing.createdDateTime", target = "thingDate"),
            @Mapping(source = "thing.approver.id", target = "approverId"),

            // mapping second parameter "owner" directory to target "owner" property
            @Mapping(source = "owner", target = "owner"),
        })
    ThingEventPayload toEventPayload(Thing thing, User owner);
}

Note that the first mapper maps all fields by default from the source to target (most field names match), but has two specific mappings from source to differently named target fields.

The second mapper wants to map all of thing into the root target, just as the first mapper does, but then additionally maps the second parameter owner to the target's same-named owner field.

Is there a way to change the second mapper "do the first mapper first" and then apply the additional mapping of @Mapping(source = "owner", target = "owner")?

1

1 Answers

1
votes

What you can do in this case is work with custom methods.

For example

@Mapper
public interface ThingMapper {
    @Mappings(
        {
            @Mapping(source = "createdDateTime", target = "thingDate"),
            @Mapping(source = "approver.id", target = "approverId"),
        })
    ThingEventPayload toEventPayload(Thing thing);

    UserPayload toUserPayload(User user);

    default ThingEventPayload toEventPayload(Thing thing, User owner) {
        ThingEventPayload eventPayload = toEventPayload(thing);
        if (eventPayload != null) {
            eventPayload.setOwner(toUserPayload(owner));
        }
        return eventPayload;
    }
}