package +zoccolo+.jpa.dao;

import java.util.Collection;
import java.util.List;

import +zoccolo+.jpa.Filter;
import +zoccolo+.jpa.Order;
import +zoccolo+.jpa.SearchParameter;

/**
 * Generic CRUD interface implemented by all DAOs.
 *
 * @param <T> entity to be managed.
 */
public interface GenericDao<T> {

	/**
	 * Persist the entity in DB (though a flush).
	 * 
	 * @param entity
	 * @return
	 */
	T create(T entity);
	
	/**
	 * Flush DB changes made in the entity, merging if the entity
	 * is detached from the session.
	 * 
	 * @param entity
	 * @return
	 */
	T update(T entity);
	
	/**
	 * Effettua la rimozione dell'entity da db, effettuando il flush.
	 * Esegue il merge se l'entity è detached dalla sessione.
	 * 
	 * @param entity
	 */
	void remove(T entity);
	
	/**
	 * Ritrova l'entity con id associato.
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 */
	T findUniqueById(Class<T> entityClass, Integer id);
	
	/**
	 * Ritrova l'entity con id associato.
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 */
	T findUniqueById(Class<T> entityClass, Long id);
	
	/**
	 * Ritrova l'entity con id associato.
	 * 
	 * @param entityClass
	 * @param id
	 * @return
	 */
	T findUniqueById(Class<T> entityClass, String id);
	
	/**
	 * Effettua una ricerca generica per il valore di un parametro.
	 * 
	 * @param entityClass Tipo di entity da ricercare.
	 * @param fieldName Nome del campo di ricerca.
	 * @param fieldClass Classe del campo di ricerca.
	 * @param fieldValue Valore del campo di ricerca.
	 * 
	 * @return Elenco non ordinato dei valori trovati.
	 */
	Collection<T> findListBy(Class<T> entityClass, String fieldName, Class<?> fieldClass, Object fieldValue);
	
	/**
	 * Effettua una ricerca full con ordinamento.
	 * 
	 * @param entityClass Tipo di entity da ricercare.
	 * @param order Elenco di elementi di ordinamento
	 * @return Elenco ordinato di tutti gli elementi della tabella indicata dall'entity.
	 */
	Collection<T> findAll(Class<T> entityClass, Order ... order);
	
	/**
	 * Verifica se esiste un record dall'id specificato.
	 * 
	 * @param id
	 * @param entityClass
	 * @return
	 */
	Boolean exists(Class<T> entityClass, Integer id);
	
	/**
	 * Verifica se esiste un record dall'id specificato.
	 * 
	 * @param id
	 * @param entityClass
	 * @return
	 */
	Boolean exists(Class<T> entityClass, Long id);
	
	/**
	 * Verifica se esiste un record dall'id specificato.
	 * 
	 * @param id
	 * @param entityClass
	 * @return
	 */
	Boolean exists(Class<T> entityClass, String id);
	
	/**
	 * Ottiene una lista di risultati con una like.
	 * 
	 * @param fieldValue
	 * @param clazz
	 * @return
	 */
	List<T> like(Class<T> fieldClazz, String fieldName, Class<String> class1, String fieldValue);

	Long count(Class<T> entityClass);

	Long count(Class<T> entityClass, Filter filter);

	List<T> fetch(Class<T> entityClass, Filter filter, Order... order);

	boolean existsByFilename(Class<T> entityClass, SearchParameter<String> fileName);

	List<Object> oneColumnQuery(final String string);

	List<Object[]> manyColumnQuery(final String string);

	Object findByPrimary(Class<T> entityClass, Object chiave);

}
