package dao.jpa;
import dao.ContactDao;
import dao.DataAccessException;
import models.dto.ContactSearchDTO;
import models.entities.Contact;
import play.Logger;
import play.db.jpa.JPA;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Root;
import java.util.Date;
import java.util.List;
/**
* Created by kiryl on 17.08.2014.
*/
public class ContactJpaDao extends BaseJpaDao<Contact, Integer> implements ContactDao {
public List<Contact> search(Integer batchNumber, Integer batchSize, ContactSearchDTO contact) throws DataAccessException {
try {
Logger.info("Search pattern:" + contact.toString());
TypedQuery<Contact> typedQuery = getSearchQuery(contact);
return getBatch(batchNumber, batchSize, typedQuery);
} catch (Throwable throwable) {
Logger.error("failed to get batch " + batchNumber + " of size " + batchSize);
throw new DataAccessException("failed to get batch " + batchNumber + " of size " + batchSize, throwable);
}
}
public List<Contact> quickSearch(Integer batchNumber, Integer batchSize, String term) throws DataAccessException {
try {
Logger.info("Quick contact search term:" + term);
String query = "SELECT c FROM Contact c WHERE c.lastName LIKE :term OR c.city LIKE :term " +
"OR c.street LIKE :term OR c.house LIKE :lastName OR c.apartment LIKE :term";
TypedQuery<Contact> typedQuery = JPA.em().createQuery(query, Contact.class);
typedQuery.setParameter("lastName", term + "%");
typedQuery.setParameter("term", "%" + term + "%");
return getBatch(batchNumber, batchSize, typedQuery);
} catch (Throwable throwable) {
Logger.error("failed to get batch " + batchNumber + " of size " + batchSize);
throw new DataAccessException("failed to get batch " + batchNumber + " of size " + batchSize, throwable);
}
}
public Integer searchResultsCount(ContactSearchDTO contact) throws DataAccessException {
try {
Logger.info("Search pattern:" + contact.toString());
TypedQuery<Contact> typedQuery = getSearchQuery(contact);
return typedQuery.getResultList().size();
} catch (Throwable throwable) {
Logger.error("failed to get search results count");
throw new DataAccessException("failed to get search results count", throwable);
}
}
public Integer quickSearchResultsCount(String term) throws DataAccessException {
try {
String query = "SELECT c FROM Contact c WHERE c.lastName LIKE :lastName OR c.city LIKE :term " +
"OR c.street LIKE :term OR c.house LIKE :term OR c.apartment LIKE :term";
TypedQuery<Contact> typedQuery = JPA.em().createQuery(query, Contact.class);
typedQuery.setParameter("lastName", term + "%");
typedQuery.setParameter("term", "%" + term + "%");
return typedQuery.getResultList().size();
} catch (Throwable throwable) {
Logger.error("failed to get quick search results count");
throw new DataAccessException("failed to get quick search results count", throwable);
}
}
protected TypedQuery<Contact> getSearchQuery(ContactSearchDTO contact) {
CriteriaBuilder criteriaBuilder = JPA.em().getCriteriaBuilder();
CriteriaQuery<Contact> criteriaQuery = criteriaBuilder.createQuery(entityClass);
Root<Contact> from = criteriaQuery.from(entityClass);
CriteriaQuery<Contact> select = criteriaQuery.select(from);
ParameterExpression fN = criteriaBuilder.parameter(String.class);
ParameterExpression lN = criteriaBuilder.parameter(String.class);
ParameterExpression mN = criteriaBuilder.parameter(String.class);
ParameterExpression date = criteriaBuilder.parameter(Date.class);
ParameterExpression mail = criteriaBuilder.parameter(String.class);
ParameterExpression city = criteriaBuilder.parameter(String.class);
ParameterExpression str = criteriaBuilder.parameter(String.class);
ParameterExpression house = criteriaBuilder.parameter(String.class);
ParameterExpression apart = criteriaBuilder.parameter(String.class);
if (contact.getBirthDate() != null) {
if (contact.getDirection().equals(">")) {
select.where(criteriaBuilder.like(from.get("firstName"), fN),
(criteriaBuilder.like(from.get("middleName"), mN)),
(criteriaBuilder.like(from.get("lastName"), lN)),
(criteriaBuilder.ge(from.get("dateOfBirth"), date)),
(criteriaBuilder.like(from.get("email"), mail)),
(criteriaBuilder.like(from.get("city"), city)),
(criteriaBuilder.like(from.get("street"), str)),
(criteriaBuilder.like(from.get("house"), house)),
(criteriaBuilder.like(from.get("apartment"), apart)));
} else {
select.where(criteriaBuilder.like(from.get("firstName"), fN),
(criteriaBuilder.like(from.get("middleName"), mN)),
(criteriaBuilder.like(from.get("lastName"), lN)),
(criteriaBuilder.le(from.get("dateOfBirth"), date)),
(criteriaBuilder.like(from.get("email"), mail)),
(criteriaBuilder.like(from.get("city"), city)),
(criteriaBuilder.like(from.get("street"), str)),
(criteriaBuilder.like(from.get("house"), house)),
(criteriaBuilder.like(from.get("apartment"), apart)));
}
} else {
select.where(criteriaBuilder.like(from.get("firstName"), fN),
(criteriaBuilder.like(from.get("middleName"), mN)),
(criteriaBuilder.like(from.get("lastName"), lN)),
(criteriaBuilder.like(from.get("email"), mail)),
(criteriaBuilder.like(from.get("city"), city)),
(criteriaBuilder.like(from.get("street"), str)),
(criteriaBuilder.like(from.get("house"), house)),
(criteriaBuilder.like(from.get("apartment"), apart)));
}
TypedQuery<Contact> typedQuery = JPA.em().createQuery(select);
typedQuery.setParameter(fN, contact.getFirstName() != null ? contact.getFirstName() + "%" : "%");
typedQuery.setParameter(mN, contact.getMiddleName() != null ? contact.getMiddleName() + "%" : "%");
typedQuery.setParameter(lN, contact.getLastName() != null ? contact.getLastName() + "%" : "%");
if (contact.getBirthDate() != null)
typedQuery.setParameter(date, contact.getBirthDate());
typedQuery.setParameter(mail, contact.getEmail() != null ? contact.getEmail() + "%" : "%");
typedQuery.setParameter(city, contact.getCity() != null ? contact.getCity() + "%" : "%");
typedQuery.setParameter(str, contact.getStreet() != null ? contact.getStreet() + "%" : "%");
typedQuery.setParameter(house, contact.getHouse() != null ? contact.getHouse() + "%" : "%");
typedQuery.setParameter(apart, contact.getApartment() != null ? contact.getApartment() + "%" : "%");
return typedQuery;
}
}