@Mapper
public class CarMapper {
@Mapping(target="displayName", source="firstName + lastName")
CarDto carToCarDto(Car car);
I'm not sure about the implementation details, i.e. would that be actual Java code, just a very simplistic sub-set or maybe expression language. But I think it would be useful to have support for this in one way or the other.
Related to this there is also #14 which is about providing support for some kind of "pre-mapping" and "post-mapping" hooks. Using such a post-mapping hook, one might implement this sort of custom mapping code you describe.
Thanks again for your input Nicolas, it's very valuable to get feedback on what the real itches are here.
Please excuse me if I'm constantly referencing Dozer, but I have used it for some time and it's my scale...
So, back to the problem at hand: Dozer let you handle any part of the mapping tree with a custom mapper. For example, you can have a declarative mapper on the class, with implicit/declarative mappers on attributes save one. In this specific attribute, I could map from a list to a map. Basically, your previous DateMapper fills this use-case, if you can use a specific Mapper for attribute A and another for attribute B.
Providing multiple sources in the API could be nice, but you would probably be overwhelmed by crazy requirements like I want to upper-case this and that every other day. Maybe the pre/post processing could be handled this way.
Please excuse me if I'm constantly referencing Dozer, but I have used it for some time and it's my scale...
Hehe, sure, Dozer is a widely used solution, actually some issues with id led to the development of MapStruct.
Basically, your previous DateMapper fills this use-case, if you can use a specific Mapper for attribute A and another for attribute B.
Ah, got you now. Generally, when generating the mapping of a bean property from type X to type Y, MapStruct will a) look for other mapping methods with matching parameter and return type (either also generated or hand-written as in the DateMapper
example) and generate an invocation of that method, and b) apply "implicit conversions" which it is able to generate itself (e.g. from numbers to strings).
The method resolution algorithm for a) is still in flux and we must find the right balance between safety, flexibility and comprehensibility. For cases where there are several candidate methods for mapping a property, we're considering to resolve that via "qualifiers":
public class DateMapper {
@Named("long") //or maybe custom qualifier annotations, e.g. @LongFormat?
public String asLongString(Date date) { ... }
@Named("short")
public String asShortString(Date date) { ... }
@Mapper(uses=DateMapper.class)
public class CarMapper {
@Mapping(source="manufacturingDate", qualified="long")
CarDto carToCarDto(Car car);
But that's still rather vague ideas at this point, maybe it would actually be simpler to just set the attribute using a post-mapping hook. Generally my thinking is that MapStruct should automate as much as possible the 80% of simple cases and get out of your way to do the difficult 20% from hand.
Going to close this one as I think it has been covered since then. There is support for
referencing custom mappers
combining several source props into one target prop (by means of expressions, which are inline Java statements atm., we are considering to support a "real" EL as well)
the qualifier feature I described above.
If needed, we can create follow-up issues for any remaining details. Thanks!