package br.com.flexait.core;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.validation.groups.Default;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.DataException;
import org.hibernate.type.StringType;
import br.com.flexait.core.component.ComponentWrapper;
@SuppressWarnings("unchecked")
public abstract class AbstractDao<T> implements Serializable {
private static final long serialVersionUID = -6855907010255004626L;
protected final Class<T> domainClass;
private ComponentWrapper component;
public AbstractDao(ComponentWrapper component) {
this.component = component;
this.domainClass = extractDomainClass();
}
private Class<T> extractDomainClass() {
return (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public Long getNextId(String sequenceName) {
SQLQuery query = session().createSQLQuery(
String.format("SELECT NEXTVAL('%s')", sequenceName));
BigInteger id = (BigInteger) query.uniqueResult();
return id.longValue();
}
public T getById(Long id) throws DataException {
return (T) component.load(getDomainClass(), id);
}
public T saveOrUpdate(T model) throws Exception {
return saveOrUpdate(model, Default.class);
}
public T saveOrUpdate(T model, Class<?>... validationGroups) throws Exception {
component.validator().validate(model, validationGroups);
return (T) component.merge(model);
}
public void remove(T model) throws Exception {
component.delete(model);
}
public List<T> list() {
return list(null);
}
public List<T> list(Order order) {
Criteria criteria = getCriteria();
if (order != null) {
criteria.addOrder(order);
}
return criteria.list();
}
public List<T> list(Order order, String param) {
Criteria criteria = getCriteria();
if (order != null) {
criteria.addOrder(order);
}
return criteria.list();
}
protected List<T> getListByCriteria(Criteria criteria) {
return criteria.list();
}
protected T getByCriteria(Criteria criteria) {
return (T) criteria.uniqueResult();
}
public List<Json> listJson(Order order) {
List<T> list = list(order);
return parseJson(list);
}
protected List<Json> parseJson(List<T> list) {
List<Json> json = new ArrayList<>();
for (T t : list) {
json.add(Json.of(t));
}
return json;
}
public Object verificaRegistro(String value, String field, Long id,
Criteria criteria) {
if (criteria == null) {
criteria = getCriteria();
}
criteria = criteria.setProjection(Projections.rowCount());
if (id != null) {
criteria.add(Restrictions.not(Restrictions.eq("id", (id == null ? 0
: id)))); // restrição do ítem atual
}
/** para permitir pesquisar em mais de um campo */
Disjunction disjunction = Restrictions.disjunction();
for (String f : field.split(",")) {
disjunction.add(Restrictions.sqlRestriction(
String.format("%s::text = ?", f.trim()), value,
StringType.INSTANCE)); // restrição pelo valor do campo)
}
criteria.add(disjunction);
criteria.setMaxResults(1);
return criteria.uniqueResult();
}
public Class<T> getDomainClass() {
return domainClass;
}
public Criteria getCriteria() {
return session().createCriteria(domainClass)
.setCacheable(true);
}
public Session session() {
return component.session();
}
public void begin() {
session().beginTransaction();
}
public void commit(boolean close) {
commit();
if (close) {
close();
}
}
public void commit() {
session().getTransaction().commit();
}
public void rollback(boolean close) {
rollback();
if (close) {
close();
}
}
public void rollback() {
session().getTransaction().rollback();
}
public void close() {
session().close();
}
public void sessionReadOnly() {
session().setDefaultReadOnly(true);
}
public void sessionFlush() {
session().flush();
}
public void sessionClear() {
session().clear();
}
public void sessionEvict(Object obj) {
session().evict(obj);
}
public ComponentWrapper component() {
return component;
}
public long count() {
Object result = getCriteria()
.setProjection(Projections.rowCount())
.uniqueResult();
return result == null ? 0 : (long) result;
}
public List<T> search(String q) {
return null;
}
public long searchCount(String q) {
return 0;
}
}