package com.sap.pto.dao; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sap.pto.adapters.PersistenceAdapter; import com.sap.pto.dao.entities.Fixture; import com.sap.pto.dao.entities.Team; import com.sap.pto.dao.entities.User; @SuppressWarnings("unchecked") public class BasicDAO<T> { private static final Logger logger = LoggerFactory.getLogger(BasicDAO.class); public enum Resolution { DAILY, WEEKLY } public static <T> T save(T t) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); T merge = em.merge(t); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return merge; } public static <T> T save(T t, EntityManager em) { T merge = em.merge(t); return merge; } /** * An error safe version of {@link #save} which does not return the saved * entity but rather if it could be saved. This is useful when handling * items with unique keys. */ public static <T> boolean trySave(T t) { try { save(t); return true; } catch (Exception e) { return false; } } public static <T> T saveNew(T t) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); em.persist(t); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return t; } public static <T> void saveNew(T t, EntityManager em) { em.persist(t); } public T getById(long id) { EntityManager em = PersistenceAdapter.getEntityManager(); T t = getById(id, em); return t; } public T getById(long id, EntityManager em) { T t = null; try { Query query = em.createQuery("select u from " + getTableName() + " u where u.id = :id"); query.setParameter("id", id); t = (T) query.getSingleResult(); } catch (NoResultException e) { logger.error("Could not retrieve entity " + id + " from table " + getTableName() + "."); } return t; } public T getByExtId(String extId) { EntityManager em = PersistenceAdapter.getEntityManager(); T t = getByExtId(extId, em); return t; } public T getByExtId(String extId, EntityManager em) { T t = null; try { Query query = em.createQuery("select u from " + getTableName() + " u where u.extId = :extId"); query.setParameter("extId", extId); t = (T) query.getSingleResult(); } catch (NoResultException e) { // nothing needs to be done } return t; } public List<T> getByTeam(Team team) { EntityManager em = PersistenceAdapter.getEntityManager(); List<T> t = getByTeam(team, em); return t; } public List<T> getByTeam(Team team, EntityManager em) { Query query = em.createQuery("select u from " + getTableName() + " u where u.team = :team"); query.setParameter("team", team); List<T> result = query.getResultList(); return result; } public List<T> getByFixture(Fixture fixture) { EntityManager em = PersistenceAdapter.getEntityManager(); List<T> t = getByFixture(fixture, em); return t; } public List<T> getByFixture(Fixture fixture, EntityManager em) { Query query = em.createQuery("select u from " + getTableName() + " u where u.fixture = :fixture"); query.setParameter("fixture", fixture); List<T> result = query.getResultList(); return result; } public long getCount() { EntityManager em = PersistenceAdapter.getEntityManager(); TypedQuery<Long> query = em.createQuery("select count(u) from " + getTableName() + " u", Long.class); Long result = query.getSingleResult(); return result; } public Map<DateTime, Long> getCountByPeriod(boolean cumulative, Resolution resolution) { return getCountByPeriod(cumulative, "", "", resolution); } public Map<DateTime, Long> getCountByPeriod(boolean cumulative, String whereClause, String dateClause, Resolution resolution) { if (StringUtils.isBlank(dateClause)) { dateClause = "u.dateCreated"; } String queryString = "select " + dateClause + ", count(u) from " + getTableName() + " u"; if (StringUtils.isNotBlank(whereClause)) { queryString += " where " + whereClause; } queryString += " group by " + dateClause + " order by " + dateClause; EntityManager em = PersistenceAdapter.getEntityManager(); TypedQuery<Object[]> query = em.createQuery(queryString, Object[].class); List<Object[]> result = query.getResultList(); return calculateCountByPeriod(cumulative, resolution, result); } protected Map<DateTime, Long> calculateCountByPeriod(boolean cumulative, Resolution resolution, List<Object[]> result) { Map<DateTime, Long> data = new TreeMap<DateTime, Long>(); for (int i = 0; i < result.size(); i++) { Object[] arr = result.get(i); Date date = (Date) arr[0]; DateTime day = new DateTime(date).withTime(0, 0, 0, 0); // do resolution handling if (resolution == Resolution.WEEKLY) { while (day.getDayOfWeek() != DateTimeConstants.SUNDAY) { day = day.plusDays(1); } } Long count = (Long) arr[1]; if (data.containsKey(day)) { data.put(day, data.get(day) + count); } else { data.put(day, count); } } if (cumulative) { DateTime[] dates = data.keySet().toArray(new DateTime[data.keySet().size()]); for (int i = 1; i < dates.length; i++) { data.put(dates[i], data.get(dates[i]) + data.get(dates[i - 1])); } } return data; } public long getStatsNumber(String whereClause) { return getStatsNumber(null, whereClause); } public long getStatsNumber(String selectClause, String whereClause) { if (StringUtils.isBlank(selectClause)) { selectClause = "u"; } String queryString = "select count(" + selectClause + ") from " + getTableName() + " u"; if (StringUtils.isNotBlank(whereClause)) { queryString += " where " + whereClause; } EntityManager em = PersistenceAdapter.getEntityManager(); Query query = em.createQuery(queryString); return (Long) query.getSingleResult(); } public List<T> getAll() { EntityManager em = PersistenceAdapter.getEntityManager(); Query query = em.createQuery("select u from " + getTableName() + " u"); List<T> result = query.getResultList(); return result; } public List<T> getAll(String orderBy) { EntityManager em = PersistenceAdapter.getEntityManager(); Query query = em.createQuery("select u from " + getTableName() + " u order by u." + orderBy); List<T> result = query.getResultList(); return result; } public List<T> getAllDesc() { EntityManager em = PersistenceAdapter.getEntityManager(); Query query = em.createQuery("select u from " + getTableName() + " u order by u.dateModified desc"); List<T> result = query.getResultList(); return result; } /** * Deletes all items for the entity. */ public int deleteAll() { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); Query query = em.createQuery("delete from " + getTableName()); int count = query.executeUpdate(); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return count; } /** * Deletes all items for the entity after a certain date. */ public int deleteAll(DateTime afterDate) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); Query query = em.createQuery("delete from " + getTableName() + " where dateCreated > :date"); query.setParameter("date", afterDate.toDate()); try { int count = query.executeUpdate(); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return count; } catch (Exception e) { // logger.warn("Could not delete all records for table '" + // getTableName() + "' after '" + afterDate + "'"); return -1; } } /** * Deletes all entries owned by the user. */ public int deleteAll(User user) { // this is just a special case of deleting by custom column return deleteFromAll(user, "user"); } /** * Deletes all entries where the user is referenced in the specified column. */ public int deleteFromAll(User user, String refUserColumn) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); Query query = em.createQuery("delete from " + getTableName() + " e where e." + refUserColumn + " = :user"); query.setParameter("user", user); int count = query.executeUpdate(); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return count; } /** * Sets the user reference of all entries where the user is referenced to * null. */ public int detachFromAll(User user, String refUserColumn) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); Query query = em.createQuery("update " + getTableName() + " e set e." + refUserColumn + " = null where e." + refUserColumn + " = :user"); query.setParameter("user", user); int count = query.executeUpdate(); PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return count; } /** * Deletes an item through it's primary key id. */ public boolean deleteById(long id) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); boolean deleted = false; Query query = em.createQuery("delete from " + getTableName() + " t where t.id = :id"); query.setParameter("id", id); deleted = query.executeUpdate() > 0; PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return deleted; } /** * Deletes an item through it's primary key id double checking with the user * to avoid misuse. */ public boolean deleteById(long id, User user) { EntityManager em = PersistenceAdapter.getEntityManager(); boolean closeTransaction = PersistenceAdapter.beginTransactionOnDemand(em); boolean deleted = false; Query query = em.createQuery("delete from " + getTableName() + " t where t.id = :id and t.user = :user"); query.setParameter("id", id); query.setParameter("user", user); deleted = query.executeUpdate() > 0; PersistenceAdapter.commitTransactionOnDemand(em, closeTransaction); return deleted; } private Type getActualType() { Type genericSuperclass = this.getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) genericSuperclass; Type type = pt.getActualTypeArguments()[0]; return type; } private String getTableName() { String[] arr = StringUtils.split(getActualType().toString(), "."); return arr[arr.length - 1]; } }