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

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.From;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

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

public abstract class GenericFacade<C extends ModelInterface> {

	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;
	}

	public C reload(C entity) {
		return this.find(entity.getId());
	}

	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(Integer id) {
		if (id == null) {
			return null;
		}
		C ret = getEm().find(getEntityClass(), id);
		return ret;
	}

	/**
	 * Deprekoitu! Yleensä ei haluta palauttaa kaikkia entryjä kannasta, vaan
	 * vain ko. tapahtumaan / käyttäjään / muuhun olioon liittyvät Jos oikeasti
	 * tarpeellinen luo funktio facadeen!
	 */
	// @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(SearchQuery search, FacadeCallback<C> callback) {
		return searcher(search, Collections.singletonList(callback));
	}

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

	}

	protected SearchResult<C> searcher(SearchQuery search, 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(search, cbs);

	}

	protected SearchResult<C> searcher(SearchQuery search, 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(search, cbs);

	}

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

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

		searchCallbacks(listCQuery, list);

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

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

		}

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

	protected From<?, C> searchCallbacks(CriteriaQuery<?> cq, List<FacadeCallback<C>> list) {
		return searchCallbacks(cq, list, getEntityClass());
	}

	protected <T extends ModelInterface> From<?, T> searchCallbacks(CriteriaQuery<?> cq, List<FacadeCallback<T>> list, Class<T> clazz) {
		Root<T> root = cq.from(clazz);
		ArrayList<Predicate> predicates = handlePredicates(cq, list, root);
		if (!predicates.isEmpty()) {
			Predicate[] preds = predicates.toArray(new Predicate[predicates.size()]);
			cq.where(preds);
		}

		return root;

	}

	protected <T extends ModelInterface> ArrayList<Predicate> handlePredicates(CriteriaQuery<?> cq, List<FacadeCallback<T>> list, From<?, T> root) {

		CriteriaBuilder cb = getEm().getCriteriaBuilder();

		ArrayList<Predicate> predicates = new ArrayList<Predicate>();
		for (FacadeCallback<T> fc : list) {
			if (fc != null) {
				fc.exec(cb, cq, root, predicates);
			}
		}
		return predicates;

	}

	// @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 entity) {
		getEm().getEntityManagerFactory().getCache().evict(getEntityClass(), entity.getId());
	}
}