package no.niths.services; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import no.niths.application.rest.exception.BadRequestException; import no.niths.application.rest.exception.ObjectInCollectionException; import no.niths.application.rest.exception.ObjectNotFoundException; import no.niths.application.rest.helper.Error; import no.niths.common.helpers.LazyFixer; import no.niths.common.helpers.MessageProvider; import no.niths.common.helpers.ValidationHelper; import no.niths.domain.Domain; import no.niths.infrastructure.interfaces.GenericRepository; import no.niths.services.interfaces.GenericService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Transactional; /** * Abstract class to use for services. Extending this class will your service * basic CRUD actions * <p> * How to use: * <p> * Create an interface called YourDomainService * <p> * Then create an implementation class that overrides getRepository() like this: * * <pre> * {@code * public class YourDomainServiceImpl extends AbstractGenericService<YourDomain> * implements YourDomainService{ * Autowired * private YourDomainRepository repository; * * Override * public GenericRepository<YourDomain> getRepository() { * return repository; * } * * } * * } * * <pre> * * @param <T> */ @Transactional public abstract class AbstractGenericService<T extends Domain> implements GenericService<T> { private Logger logger = LoggerFactory .getLogger(AbstractGenericService.class); private CustomBeanUtilsBean mergeBean = new CustomBeanUtilsBean(); private Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); private LazyFixer<T> lazyFixer = new LazyFixer<T>(); /** * Calls on repository to persist the domain * * @param domain * the object to persist * @return id of the object created * */ @Override public Long create(T domain) { validateFields(domain); return getRepository().create(domain); } private void validateFields(T domain) { Set<ConstraintViolation<T>> violations = validator.validate(domain); for (ConstraintViolation<T> violation : violations) { throw new BadRequestException(String.format( "Invalid values - %s", violation.getMessage())); } } /** * Calls on repository to get all objects of a certain type * * @param domain * empty object to return all, or with some attributes to search * for * @return list of objects */ @Override public List<T> getAll(T domain) { List<T> list = getRepository().getAll(domain); return list; } @Override public List<T> getAll(T domain, int firstResult, int maxResults) { return getRepository().getAll(domain, firstResult, maxResults); } /** * Calls on repository to get a certain object * * @param id * of the object * @return object with matching ID, or null if no object found */ @Override public T getById(long id) { T t = getRepository().getById(id); ArrayList<T> ts = new ArrayList<T>(); ts.add(t); lazyFixer.fetchChildren(ts); return ts.get(0); } /** * Calls on repository to update a domain * <p> * Will override the current object in DB * <p> * * @param domain * , the domain to update */ @Override public void update(T domain) { System.err.println(domain.toString() + "hello"); getRepository().update(domain); } /** * Updates an object * <p> * Difference from update() is that only the attributes with value will be * updated. All null attributes will not affect the object in DB * <p> * * @param domain * the domain to update */ public void mergeUpdate(T domain) { ValidationHelper.isObjectNull(domain.getId()); T domaineToUpdate = getRepository().getById(domain.getId()); ValidationHelper.isObjectNull(domaineToUpdate); try { mergeBean.copyProperties(domaineToUpdate, domain); } catch (IllegalAccessException | InvocationTargetException e) { logger.error("error", e); e.printStackTrace(); } } /** * Deletes the object in DB with the given id * * @param id * the id of the object * @return true if update succeeds, false otherwise */ @Override public boolean delete(long id) { return getRepository().delete(id); } /** * Deletes an object in DB with the given id. All relationships will also be * deleted * <p> * * @param id * of the object to delete */ @Override public void hibernateDelete(long id) { getRepository().hibernateDelete(id); } /** * Override this method to return an instance of your repository * <p> * * @return an instance of your repository */ public abstract GenericRepository<T> getRepository(); /** * Helper method for checking if the the list element is a instance of * Domain and then we can cast the list element to a Domain for using the * getId() method * * @throws ObjectInCollectionException * () if the object is found * @param list * @param id */ @SuppressWarnings("rawtypes") public void checkIfObjectIsInCollection(List list, long id,Class clazz) { for (int i = 0; i < list.size(); i++) { if (list.get(i) instanceof Domain) { Domain d = (Domain) list.get(i); if (d.getId() == id) { throw new ObjectInCollectionException( MessageProvider.buildErrorMsg(clazz, Error.OBJECT_IN_COLLECTION)); } } } } @SuppressWarnings("rawtypes") public T validate(T domain, Class clazz) { ValidationHelper.isObjectNull(domain, clazz); return domain; } @SuppressWarnings("rawtypes") public void checkIfIsRemoved(boolean isRemoved, Class clazz) { if (!isRemoved) { String msg = MessageProvider.buildErrorMsg(clazz, Error.NOT_FOUND); logger.debug(msg); throw new ObjectNotFoundException(msg); } } @SuppressWarnings("rawtypes") public void checkIfObjectExists(Domain domain, Long id,Class clazz) { if (domain != null && domain.getId() == id) { String msg = MessageProvider.buildErrorMsg(clazz, Error.OBJECT_IN_COLLECTION); logger.debug(msg); throw new ObjectInCollectionException(msg); } } }