package io.robe.hibernate.criteria.api;
import io.robe.common.utils.Validations;
import io.robe.hibernate.criteria.api.cache.EntityMeta;
import io.robe.hibernate.criteria.api.cache.EntityMetaFinder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by kamilbukum on 10/01/2017.
*/
public abstract class Transformer<E> {
private final EntityMetaFinder finder;
private final Class<? extends E> transformClass;
private final TransformType transformType;
private EntityMeta meta;
public Transformer(Class<? extends E> transformClass, EntityMetaFinder finder){
this.transformClass = transformClass;
this.finder = finder;
if(transformClass == null) {
this.transformType = TransformType.ENTITY;
} else if(transformClass.getName().equals(Map.class.getName())) {
this.transformType = TransformType.MAP;
} else {
this.transformType = TransformType.DTO;
this.meta = CachedEntity.getEntityMeta(transformClass, this.finder, true);
}
}
public Class<? extends E> getTransformClass() {
return transformClass;
}
public TransformType getTransformType() {
return transformType;
}
public EntityMetaFinder getFinder() {
return this.finder;
}
public EntityMeta getMeta(){
return this.meta;
}
public EntityMeta getMeta(Class<?> clazz){
return CachedEntity.getEntityMeta(clazz, this.finder, false);
}
public abstract List<E> list(Criteria<E> criteria);
public abstract Result<E> pairList(Criteria<E> criteria);
public abstract Long count(Criteria<E> criteria);
public abstract Object uniqueResult(Criteria<E> criteria);
public enum TransformType {
ENTITY , MAP , DTO
}
/**
* Caches fields of Class
*/
public static class CachedEntity {
/**
* Holds Cached Fields of Given Entity Class
*/
private static final ConcurrentHashMap<String, EntityMeta> entityMetaMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, EntityMetaFinder> entityMetaFinder = new ConcurrentHashMap<>();
private static EntityMeta upgradeCache(Class<?> entityClass, EntityMetaFinder finder){
EntityMeta meta = finder.getEntityMeta(entityClass);
entityMetaMap.put(entityClass.getName(), meta);
entityMetaFinder.put(entityClass.getName(), finder);
return meta;
}
public static EntityMeta getEntityMeta(Class<?> entityClass, EntityMetaFinder metaFinder, boolean isDto) {
EntityMeta meta = entityMetaMap.get(entityClass.getName());
EntityMetaFinder finder = entityMetaFinder.get(entityClass.getName());
if(meta == null || (finder != null && !finder.equals(metaFinder))) {
meta = upgradeCache(entityClass, finder == null ? metaFinder: finder);
if(meta == null) {
throw new RuntimeException("Entity Meta is null empty ! Please check the given finder that name is " + metaFinder.getClass().getName());
}
if(!isDto && Validations.isEmptyOrNull(meta.getIdentityName())) {
throw new RuntimeException("Identity name not found in Entity Meta ! Please check the given entity that's name is " + entityClass.getName());
}
}
return meta;
}
}
}