package com.linkedin.thirdeye.datalayer.bao.jdbc; import com.linkedin.thirdeye.datalayer.bao.AbstractManager; import com.linkedin.thirdeye.datalayer.dao.GenericPojoDao; import com.linkedin.thirdeye.datalayer.dto.AbstractDTO; import com.linkedin.thirdeye.datalayer.dto.AnomalyFeedbackDTO; import com.linkedin.thirdeye.datalayer.dto.AnomalyFunctionDTO; import com.linkedin.thirdeye.datalayer.dto.RawAnomalyResultDTO; import com.linkedin.thirdeye.datalayer.pojo.AbstractBean; import com.linkedin.thirdeye.datalayer.pojo.AnomalyFeedbackBean; import com.linkedin.thirdeye.datalayer.pojo.AnomalyFunctionBean; import com.linkedin.thirdeye.datalayer.pojo.RawAnomalyResultBean; import com.linkedin.thirdeye.datalayer.util.Predicate; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractManagerImpl<E extends AbstractDTO> implements AbstractManager<E> { private static final Logger LOG = LoggerFactory.getLogger(AbstractManagerImpl.class); protected static final ModelMapper MODEL_MAPPER = new ModelMapper(); static { MODEL_MAPPER.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); } private Class<? extends AbstractDTO> dtoClass; private Class<? extends AbstractBean> beanClass; protected GenericPojoDao genericPojoDao; protected AbstractManagerImpl(Class<? extends AbstractDTO> dtoClass, Class<? extends AbstractBean> beanClass) { this.dtoClass = dtoClass; this.beanClass = beanClass; } public void setGenericPojoDao(GenericPojoDao genericPojoDao) { this.genericPojoDao = genericPojoDao; } @Override public Long save(E entity) { if (entity.getId() != null) { //TODO: throw exception and force the caller to call update instead update(entity); return entity.getId(); } AbstractBean bean = convertDTO2Bean(entity, beanClass); Long id = genericPojoDao.put(bean); entity.setId(id); return id; } @Override public int update(E entity, Predicate predicate) { AbstractBean bean = convertDTO2Bean(entity, beanClass); return genericPojoDao.update(bean, predicate); } @Override public int update(E entity) { AbstractBean bean = convertDTO2Bean(entity, beanClass); return genericPojoDao.update(bean); } public E findById(Long id) { AbstractBean abstractBean = genericPojoDao.get(id, beanClass); if (abstractBean != null) { AbstractDTO abstractDTO = MODEL_MAPPER.map(abstractBean, dtoClass); return (E) abstractDTO; } else { return null; } } @Override public void delete(E entity) { genericPojoDao.delete(entity.getId(), beanClass); } @Override public void deleteById(Long id) { genericPojoDao.delete(id, beanClass); } @Override public List<E> findAll() { List<? extends AbstractBean> list = genericPojoDao.getAll(beanClass); List<E> result = new ArrayList<>(); for (AbstractBean bean : list) { AbstractDTO dto = MODEL_MAPPER.map(bean, dtoClass); result.add((E) dto); } return result; } @Override public List<E> findByParams(Map<String, Object> filters) { List<? extends AbstractBean> list = genericPojoDao.get(filters, beanClass); return convertBeanListToDTOList(list); } @Override public List<E> findByPredicate(Predicate predicate) { List<? extends AbstractBean> list = genericPojoDao.get(predicate, beanClass); return convertBeanListToDTOList(list); } protected List<E> convertBeanListToDTOList(List<? extends AbstractBean> beans) { List<E> result = new ArrayList<>(); for (AbstractBean bean : beans) { result.add((E) convertBean2DTO(bean, dtoClass)); } return result; } @Deprecated protected RawAnomalyResultDTO createRawAnomalyDTOFromBean( RawAnomalyResultBean rawAnomalyResultBean) { RawAnomalyResultDTO rawAnomalyResultDTO; rawAnomalyResultDTO = MODEL_MAPPER.map(rawAnomalyResultBean, RawAnomalyResultDTO.class); if (rawAnomalyResultBean.getFunctionId() != null) { AnomalyFunctionBean anomalyFunctionBean = genericPojoDao.get(rawAnomalyResultBean.getFunctionId(), AnomalyFunctionBean.class); if (anomalyFunctionBean == null) { LOG.error("this anomaly function bean should not be null"); } AnomalyFunctionDTO anomalyFunctionDTO = MODEL_MAPPER.map(anomalyFunctionBean, AnomalyFunctionDTO.class); rawAnomalyResultDTO.setFunction(anomalyFunctionDTO); } if (rawAnomalyResultBean.getAnomalyFeedbackId() != null) { AnomalyFeedbackBean anomalyFeedbackBean = genericPojoDao .get(rawAnomalyResultBean.getAnomalyFeedbackId(), AnomalyFeedbackBean.class); AnomalyFeedbackDTO anomalyFeedbackDTO = MODEL_MAPPER.map(anomalyFeedbackBean, AnomalyFeedbackDTO.class); rawAnomalyResultDTO.setFeedback(anomalyFeedbackDTO); } return rawAnomalyResultDTO; } protected <T extends AbstractDTO> T convertBean2DTO(AbstractBean entity, Class<T> dtoClass) { try { AbstractDTO dto = dtoClass.newInstance(); MODEL_MAPPER.map(entity, dto); return (T) dto; } catch (Exception e) { throw new RuntimeException(e); } } protected <T extends AbstractBean> T convertDTO2Bean(AbstractDTO entity, Class<T> beanClass) { try { AbstractBean bean = beanClass.newInstance(); MODEL_MAPPER.map(entity, bean); return (T) bean; } catch (Exception e) { throw new RuntimeException(e); } } }