package br.com.caiofrota.modelutil.repositories.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import br.com.caiofrota.modelutil.domains.GenericEntity;
import br.com.caiofrota.modelutil.exceptions.EntityNullException;
import br.com.caiofrota.modelutil.exceptions.PrimaryKeyNullException;
import br.com.caiofrota.modelutil.repositories.GenericRepository;

/**
 * Generic repository.
 * 
 * @author Caio Frota (contato@caiofrota.com.br)
 * @version 1.0
 * @since 1.0
 * 
 * @param <E>
 *            Entity.
 * @param <PK>
 *            Primary key.
 */
@Transactional(propagation = Propagation.SUPPORTS)
public class GenericRepositoryImpl<E extends GenericEntity<PK>, PK extends Serializable>
		implements GenericRepository<E, PK> {

	private static final long serialVersionUID = 8496006039538789900L;

	@PersistenceContext
	private EntityManager entityManager;

	protected Class<E> persistentClass;

	protected final Logger logger = Logger.getLogger(GenericRepository.class);

	@SuppressWarnings("unchecked")
	public GenericRepositoryImpl() {
		ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
		Type[] args = parameterizedType.getActualTypeArguments();
		persistentClass = (Class<E>) args[0];
	}

	/**
	 * Persist a object.
	 * 
	 * @param obj
	 *            Object to persist.
	 */
	@Transactional
	public void save(E obj) {
		if (obj == null) {
			throw new EntityNullException();
		}
		logger.info("Method save with param = [".concat(obj.toString()).concat("]."));
		entityManager.persist(obj);
	}

	/**
	 * Update a object or insert if doesn't exist.
	 * 
	 * @param obj
	 *            Object to update.
	 */
	@Transactional
	public void update(E obj) {
		if (obj == null) {
			throw new EntityNullException();
		}
		logger.info("Method update with param = [".concat(obj.toString()).concat("]."));
		entityManager.merge(obj);
	}

	/**
	 * Find a object by primary key.
	 * 
	 * @param primaryKey
	 *            Primary key.
	 * @return Object.
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public E findByPrimaryKey(PK primaryKey) {
		if (primaryKey == null) {
			throw new PrimaryKeyNullException();
		}
		logger.info("Method findBy");
		return (E) getSession().get(persistentClass, primaryKey);
	}

	/**
	 * Remove a object.
	 * 
	 * @param obj
	 *            Object to remove.
	 */
	@Transactional
	public void delete(E obj) {
		if (obj == null) {
			throw new EntityNullException();
		}
		logger.info("Method delete with param = [".concat(obj.toString()).concat("]."));
		entityManager.remove(entityManager.getReference(this.persistentClass, obj.getId()));
	}

	/**
	 * Get the session.
	 * 
	 * @return Session.
	 */
	@Transactional
	public Session getSession() {
		return (Session) entityManager.getDelegate();
	}
}

@@ -151,16 +151,39 @@
 ct.Type;
+%0Aimport java.util.List;
 %0A%0Aimport
@@ -315,20 +315,93 @@
 bernate.
-Sess
+Criteria;%0Aimport org.hibernate.Session;%0Aimport org.hibernate.criterion.Criter
 ion;%0Aimp
@@ -2684,24 +2684,676 @@
 ryKey);%0A%09%7D%0A%0A
+%09/**%0A%09 * Find a object by primary key.%0A%09 * %0A%09 * @return List of objects.%0A%09 */%0A%09@SuppressWarnings(%22unchecked%22)%0A%09@Transactional%0A%09public List%3CE%3E findAll() %7B%0A%09%09logger.info(%22Method findBy%22);%0A%09%09return getSession().createCriteria(persistentClass).list();%0A%09%7D%0A%09%0A%09/**%0A%09 * Find a object by criterias.%0A%09 * %0A%09 * @return List of objects.%0A%09 */%0A%09@SuppressWarnings(%22unchecked%22)%0A%09@Transactional%0A%09public List%3CE%3E findByCriteria(Criterion... criterias) %7B%0A%09%09Criteria criteria = getSession().createCriteria(persistentClass);%0A%09%09if (criterias != null) %7B%0A%09%09%09for (Criterion currentCriteria : criterias) %7B%0A%09%09%09%09criteria.add(currentCriteria);%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return criteria.list();%0A%09%7D%0A%0A
 %09/**%0A%09 * Rem

Add methods findAll and findByCriteria.