GenericFacade.java 7.6 KB
package fi.insomnia.bortal.facade;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fi.insomnia.bortal.facade.callbacks.FacadeCallback;
import fi.insomnia.bortal.utilities.SearchResult;
import fi.insomnia.bortal.utilities.jpa.ModelInterface;

public abstract class GenericFacade<I extends Serializable, C extends ModelInterface<I>> {

	// protected static <T, C extends ModelInterface<T>>
	// List<SingularAttribute<C, T>> mkAttrlist(SingularAttribute<C, T>...
	// types) {
	// List<SingularAttribute<C, T>> ret = new ArrayList<SingularAttribute<C,
	// T>>();
	// for (SingularAttribute<C, T> a : types) {
	// ret.add(a);
	// }
	// return Collections.unmodifiableList(ret);
	//
	// }

	private final Class<C> entClass;
	private static final Logger logger = LoggerFactory.getLogger(GenericFacade.class);

	public GenericFacade(Class<C> entityClass) {
		this.entClass = entityClass;
	}

	protected Class<C> getEntityClass() {
		return entClass;
	}

	protected abstract EntityManager getEm();

	public void create(C entity) {
		getEm().persist(entity);
	}

	public void remove(C entity) {

		getEm().remove(entity);
	}

	public C merge(C entity) {
		return getEm().merge(entity);

	}

	public void refresh(C usr) {
		getEm().refresh(usr);
	}

	public C find(I id) {
		if (id == null) {
			return null;
		}
		C ret = getEm().find(getEntityClass(), id);
		return ret;
	}

	@Deprecated
	public List<C> findAll() {
		return findAll(null);
	}

	@Deprecated
	public List<C> findAll(String sort) {
		return findAll(0, 0, sort);
	}

	@Deprecated
	public List<C> findRange(int[] range) {
		CriteriaQuery<C> cq = getEm().getCriteriaBuilder().createQuery(getEntityClass());
		cq.select(cq.from(getEntityClass()));
		TypedQuery<C> q = getEm().createQuery(cq);
		q.setMaxResults(range[1] - range[0]);
		q.setFirstResult(range[0]);
		return q.getResultList();
	}

	@Deprecated
	public long count() {
		CriteriaQuery<Long> cq = getEm().getCriteriaBuilder().createQuery(Long.class);
		Root<C> rt = cq.from(getEntityClass());
		cq.select(getEm().getCriteriaBuilder().count(rt));
		TypedQuery<Long> q = getEm().createQuery(cq);
		return q.getSingleResult();
	}

	protected static <K> K getSingleNullableResult(TypedQuery<K> q) {
		K ret = null;
		try {
			ret = q.getSingleResult();
		} catch (NoResultException e) {
			ret = null;
		}
		return ret;
	}

	@Deprecated
	protected List<C> search(String query, String[] fields, String orderfield) {
		return search(0, 0, query, fields, orderfield);
	}

	@Deprecated
	protected SearchResult<C> searcher(int page, int pagesize, String query, String[] fields, String orderfield) {
		SearchResult<C> ret = new SearchResult<C>();
		ret.setResults(search(page, pagesize, query, fields, orderfield));
		ret.setResultcount(searchCount(query, fields));
		return ret;
	}

	// Le fu... Tuota.. generics ei hanskaa ... operaattoria.. tehdään siis
	// näin... :(
	protected SearchResult<C> searcher(int page, int pagesize, FacadeCallback<C> callback) {
		return searcher(page, pagesize, Collections.singletonList(callback));
	}

	protected SearchResult<C> searcher(int page, int pagesize, FacadeCallback<C> cb1, FacadeCallback<C> cb2) {
		ArrayList<FacadeCallback<C>> cbs = new ArrayList<FacadeCallback<C>>();
		cbs.add(cb1);
		cbs.add(cb2);
		return searcher(page, pagesize, cbs);

	}

	protected SearchResult<C> searcher(int page, int pagesize, FacadeCallback<C> cb1, FacadeCallback<C> cb2, FacadeCallback<C> cb3) {
		ArrayList<FacadeCallback<C>> cbs = new ArrayList<FacadeCallback<C>>();
		cbs.add(cb1);
		cbs.add(cb2);
		cbs.add(cb3);
		return searcher(page, pagesize, cbs);

	}

	protected SearchResult<C> searcher(int page, int pagesize, FacadeCallback<C> cb1, FacadeCallback<C> cb2, FacadeCallback<C> cb3, FacadeCallback<C> cb4) {
		ArrayList<FacadeCallback<C>> cbs = new ArrayList<FacadeCallback<C>>();
		cbs.add(cb1);
		cbs.add(cb2);
		cbs.add(cb3);
		cbs.add(cb4);
		return searcher(page, pagesize, cbs);

	}

	protected SearchResult<C> searcher(int page, int pagesize, List<FacadeCallback<C>> list) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();

		CriteriaQuery<C> listCQuery = cb.createQuery(getEntityClass());
		CriteriaQuery<Long> countCQuery = cb.createQuery(Long.class);

		searchCallbacks(listCQuery, list);

		Root<C> countRoot = searchCallbacks(countCQuery, list);
		countCQuery.select(cb.count(countRoot));

		TypedQuery<Long> countQ = getEm().createQuery(countCQuery);
		TypedQuery<C> listQ = getEm().createQuery(listCQuery);
		if (pagesize > 0) {
			listQ.setFirstResult(page * pagesize);
			listQ.setMaxResults(pagesize);

		}

		return new SearchResult<C>(listQ.getResultList(), countQ.getSingleResult());
	}

	private Root<C> searchCallbacks(CriteriaQuery<?> cq, List<FacadeCallback<C>> list) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		Root<C> root = cq.from(getEntityClass());

		ArrayList<Predicate> predicates = new ArrayList<Predicate>();
		for (FacadeCallback<C> fc : list) {
			logger.debug("Executing {}, predsize: {}", fc, predicates.size());

			fc.exec(cb, cq, root, predicates);
		}
		if (!predicates.isEmpty()) {
			Predicate[] preds = predicates.toArray(new Predicate[predicates.size()]);
			cq.where(preds);
		}

		return root;

	}

	@Deprecated
	protected List<C> search(int page, int pagesize, String query, String[] fields, String orderfield) {

		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<C> cq = cb.createQuery(getEntityClass());

		Root<C> root = cq.from(getEntityClass());

		addPredicates(cq, root, query, fields);

		TypedQuery<C> q = getEm().createQuery(cq);
		if (pagesize > 0) {
			q.setFirstResult(page * pagesize);
			q.setMaxResults(pagesize);

		}
		List<C> ret = q.getResultList();
		return ret;
	}

	@Deprecated
	protected void addPredicates(CriteriaQuery<?> cq, Root<C> root, String query, String[] fields) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		if (query != null && !query.isEmpty() && fields != null && fields.length > 0) {
			List<Predicate> preds = new ArrayList<Predicate>();
			for (String field : fields) {
				Path<String> rootfield = root.get(field);
				preds.add(cb.like(cb.lower(rootfield), query));
			}
			cq.where(cb.or(preds.toArray(new Predicate[preds.size()])));
		}

	}

	@Deprecated
	protected long searchCount(String query, String[] fields) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<Long> cq = cb.createQuery(Long.class);
		Root<C> root = cq.from(getEntityClass());

		addPredicates(cq, root, query, fields);
		cq.select(getEm().getCriteriaBuilder().count(root));

		TypedQuery<Long> q = getEm().createQuery(cq);
		return q.getSingleResult();
	}

	@Deprecated
	public List<C> findAll(int page, int pagesize, String sort) {
		CriteriaBuilder cb = getEm().getCriteriaBuilder();
		CriteriaQuery<C> cq = cb.createQuery(getEntityClass());
		Root<C> root = cq.from(getEntityClass());

		if (sort != null) {
			cq.orderBy(cb.asc(root.get(sort)));
		}

		cq.select(cq.from(getEntityClass()));
		TypedQuery<C> q = getEm().createQuery(cq);

		if (pagesize > 0) {
			q.setFirstResult(page * pagesize);
			q.setMaxResults(pagesize);
		}

		return q.getResultList();
	}

	public void flush() {
		getEm().flush();
	}

	public void evict(C clz) {
		getEm().getEntityManagerFactory().getCache().evict(getEntityClass(), clz.getId());
	}
}