For example (one abstract class and two concrete classes):
public abstract class Animal {
private String name;
...
}
public class Cat extends Animal {
private Boolean mouseCatcher;
...
}
public class Dog extends Animal {
private Integer awardsCount;
...
}
DTO:
public abstract class AnimalDto {
private String name;
...
}
public class CatDto extends AnimalDto {
private Boolean mouseCatcher;
...
}
public class DogDto extends AnimalDto {
private Integer awardsCount;
...
}
And mapper:
@Mapper
public interface AnimalMapper {
public CatDto catToCatDto(Cat cat);
public DogDto dogToDogDto(Dog dog);
@AbstractMapping // special mark to generate abstract mapping method
public AnimalDto animalToAnimalDto(Animal animal);
public List<AnimalDto> animalsToAnimalDtos(List<Animal> animals);
}
Generated result:
public class AnimalMapperImpl implements AnimalMapper {
public CatDto catToCatDto(Cat cat) {
...
}
public DogDto dogToDogDto(Dog dog) {
...
}
// example of generated method for abstract mapping
public AnimalDto animalToAnimalDto(Animal animal) {
if (animal instanceof Cat)
return catToCatDto((Cat) animal);
else if (animal instanceof Dog)
return dogToDogDto((Dog) animal);
return null;
}
public List<AnimalDto> animalsToAnimalDtos(List<Animal> animals) {
if ( animals == null ) {
return null;
}
List<AnimalDto> list = new ArrayList<AnimalDto>();
for ( Animal animal : animals ) {
list.add( animalToAnimalDto( animal ) );
}
return list;
}
}
This is basically a duplicate of #131. There's some stuff that we need to think about, but I also still find it worth exploring.
Yes, it's an interesting idea. I'm no huge fan of the instance-of calls, but I guess there is no way around them.
If such functionality is implemented, we could possibly drop #319 as well.
IIUC: what we actually try to implement is automatic generation of factory methods that @agudian implemented earlier (see org.mapstruct.ap.test.factories.GenericFactory). Can we use the 'forgedmethod' mechanism to achieve this? How would we establish which classes to include in the 'instance-of if statements'
Hi guys, is there any development on this issue (or the referenced #131 )? In case not, what would you recommend for an ad-hoc implementation of this looks like? The use case is exactly the one described here: converting between parallel class hierarchies of Entity/Dto objects:
Person PersonDto
/ \ / \
Man Woman ManDto WomanDto
And the method I would like to implement is List<? extends PersonDto> peopleToDtos(List<? extends Person> people)?
Hi, as @milanov requested could you please provide how to do these>?
I also want to implement List<? extends BaseClass> but there does not seems to be a way to do this.
Alternately can you suggest how to do it currently?
The way you'd currently do this is to declare the mapping methods for cat/dog or man/woman to let them be generated and implement the method operating on the abstract classes with the instance-of dance manually.
For lists and such, MapStruct will then delegate to your manually created method.
An example to illustrate what @agudian has said:
@Mapper
public interface UserMapper {
default UserDTO toDto(User u) {
if(u instanceof User1)
return toDto1((User1) u);
return toDto2((User2) u);
}
default User toEntity(UserDTO u) {
if(u instanceof User1DTO)
return toEntity1((User1DTO) u);
return toEntity2((User2DTO) u);
}
User1DTO toDto1(User1 u);
User1 toEntity1(User1DTO u);
User2DTO toDto2(User2 u);
User2 toEntity2(User2DTO u);
}
That would be right, isn't?
Most helpful comment
An example to illustrate what @agudian has said:
That would be right, isn't?