Reputation: 1050
I have the following class hierarchy:
public class BaseFaultType
{
protected String faultId;
protected String faultDescription;
protected String faultDetail;
... -> setters and getters
}
public class PollingFaultType extends BaseFaultType
{
protected Integer initiatedFiles;
protected Integer failedFiles;
... -> getters and setters
}
public class StoreFaultType extends BaseFaultType
{
protected String storePath;
... -> getters and setters
}
...
There is one BaseFaultType with some common properties (I left out most of them for simplicity) and then I have multiple types that extend the BaseFaultType with additional properties.
Please note that I have no control over these classes.
My application receives objects of these child types. Then I need to map these objects into different types of entities, i.e:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = EntityConstants.ERROR)
public class FaultMessage
{
private String errorId;
private String errorDescription;
private String errorDetail;
private Boolean retryable;
... -> getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = EntityConstants.POLLING_MESSAGE)
public class PollingFaultMessage extends FaultMessage
{
private Integer failed;
private Integer initiated;
... -> getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = EntityConstants.STORE_MESSAGE)
public class StoreFaultMessage
{
...
}
I am using ModelMapper for this job. Note that the ModelMapper that I use is configured with disabled implicit mapping (for reasons that are not interesting for this question):
mapper.getConfiguration().setImplicitMappingEnabled(false);
mapper.addMappings(new PropertyMap<BaseFaultType, FaultMessage>()
{
@Override
protected void configure()
{
map(source.getFaultId()).setErrorId(null);
map(source.getFaultDescription()).setErrorDescription(null);
...
}
});
mapper.addMappings(new PropertyMap<PollingFaultType, PollingFaultMessage>()
{
@Override
protected void configure()
{
map(source.getInitiatedFiles()).setInitiated(null);
...
}
});
PollingFaultType faultType = getPollingFaultType();
PollingFaultMessage faultMessage = mapper.map(faultType, PollingFaultMessage.class);
Unfortunately, this produces faultMessage that only has its initiated
property mapped to a real value.
The properties errorId
, errorDetail
etc are not being mapped (probably since they are configured into a completely separate TypeMap)
So my question is - how can I configure ModelMapper in a way that allows me to define TypeMaps/PropertyMaps that only map child-specific properties such as initiated
and failed
and have the common properties that come from the base type such as errorId
and errorDetail
automatically mapped?
The main thing I want to achieve here is that I want to avoid having to explicitly specify the mapping of these common properties in each child's TypeMap, i.e. I want to avoid to:
mapper.addMappings(new PropertyMap<PollingFaultType, PollingFaultMessage>()
{
@Override
protected void configure()
{
// I want to avoid to copy these lines around for each child mapping since they will be always the same
map(source.getFaultId()).setErrorId(null);
map(source.getFaultDescription()).setErrorDescription(null);
map(source.getInitiatedFiles()).setInitiated(null);
...
}
});
Upvotes: 1
Views: 3047
Reputation: 1895
Try to do next:
beans:
public class BaseType {
protected String base;
// getters/setters
}
public class Extended extends BaseType {
private String value ;
// getters/setters
}
dto:
public class SimpleDTO {
private String valueDTO;
private String baseDTO;
// getters/setters
}
configuration:
modelMapper.typeMap(SimpleDTO.class, BaseType.class)
.addMapping(SimpleDTO::getBaseDTO, BaseType::setBase);
modelMapper.typeMap(SimpleDTO.class, Extended.class)
.addMapping(SimpleDTO::getValueDTO, Extended::setValue)
.includeBase(SimpleDTO.class, BaseType.class);
use:
SimpleDTO dto = new SimpleDTO();
dto.setBaseDTO("base");
dto.setValueDTO("value");
Extended ex = modelMapper.map(dto, Extended.class);
ModelMapper version: 1.1.0
Upvotes: 1