ca.gc.aafc.dina.mapper.DinaMapper Maven / Gradle / Ivy
Show all versions of dina-base-api Show documentation
package ca.gc.aafc.dina.mapper;
import ca.gc.aafc.dina.dto.RelatedEntity;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.hibernate.Hibernate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* DTO to Entity Bean mapper (and vice-versa). Used to map fields between DTO's and Entities.
*
* @param Type of Dto
* @param Type of Entity
*/
@Log4j2
@AllArgsConstructor
public class DinaMapper {
private final Class dtoClass;
private final DinaMappingRegistry registry;
/**
*
* Used to construct an instance of the dina mapper where the dto class will be scanned and all
* custom field handlers needed to resolve the entity graph will parsed from the given dto class.
*
*
* @param dtoClass - class to map
*/
public DinaMapper(Class dtoClass) {
this(dtoClass, new DinaMappingRegistry(dtoClass));
}
/**
* Returns a new dto mapped from the given entity. All attributes and relationships will be mapped
* by default. If you want to select which attributes or relations to map use method signature
* {@link DinaMapper#toDto(Object, Map, Set)}
*
* @param entity - source of the mapping
* @return a new dto mapped from the given entity.
*/
public D toDto(E entity) {
Set relations = registry.findMappableRelationsForClass(dtoClass).stream()
.map(DinaMappingRegistry.InternalRelation::getName).collect(Collectors.toSet());
return toDto(entity, registry.getAttributesPerClass(), relations);
}
/**
*
* Returns a new dto mapped with the fields of a given entity. The given selected fields per class
* map which fields to apply from a source class to a target. A set of given relation field names
* designates which fields are mapped as relations.
*
*
*
* The base attributes of a source are assumed to be of the same type as the target. Relations
* fields of a source are NOT expected to be of the same type.
*
*
*
* Selected fields per class should also contain the relations source class and target fields to
* map.
*
*
* @param entity - source of the mapping
* @param selectedFieldPerClass - selected fields of source classes to map
* @param relations - Set of relation field names
* @return - A new instance of a class with the mapped fields
*/
@SneakyThrows
public D toDto(
E entity,
Map, Set> selectedFieldPerClass,
Set relations
) {
D dto = dtoClass.getConstructor().newInstance();
mapSourceToTarget(entity, dto, selectedFieldPerClass, relations, new IdentityHashMap<>());
return dto;
}
/**
*
* Apply the fields of a given dto to a given entity. The given selected fields per class map
* which fields to apply from a source class to a target. A set of given relation field names
* designates which fields are mapped as relations.
*
*
*
* The base attributes of a source are assumed to be of the same type as the target. Relations
* fields of a source are NOT expected to be of the same type.
*
*
*
* Selected fields per class should also contain the relations source class and target fields to
* map.
*
*
* @param dto - source of the mapping
* @param entity - target of the mapping
* @param selectedFieldPerClass - selected fields of source classes to map
* @param relations - Set of relation field names
*/
@SneakyThrows
public void applyDtoToEntity(
D dto,
E entity,
Map, Set> selectedFieldPerClass,
Set relations
) {
mapSourceToTarget(dto, entity, selectedFieldPerClass, relations, new IdentityHashMap<>());
}
/**
* Map the given selected fields of a source to a target with the given relations.
*
* @param - target type
* @param - source type
* @param source - source of the mapping
* @param target - target of the mapping
* @param selectedFieldPerClass - selected fields to map
* @param relations - relations to map
* @param visited - map of visited objects and there corresponding target.
*/
@SuppressWarnings("unchecked")
private void mapSourceToTarget(
@NonNull S source,
@NonNull T target,
@NonNull Map, Set> selectedFieldPerClass,
@NonNull Set relations,
@NonNull Map