it.mice.voila.runtime.service.GenericEntityService Maven / Gradle / Ivy
package it.mice.voila.runtime.service;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pojomatic.diff.Differences;
import org.pojomatic.diff.NoDifferences;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import it.mice.voila.runtime.dao.Dao;
import it.mice.voila.runtime.entity.Entity;
import it.mice.voila.runtime.entity.EntityDiffAdapter;
import it.mice.voila.runtime.exception.BusinessException;
import it.mice.voila.runtime.util.UserMessage;
import it.mice.voila.runtime.util.UserMessages;
public abstract class GenericEntityService implements EntityService {
/**
* Default logger.
*/
private static Log logger = LogFactory.getLog(GenericEntityService.class);
/**
* Data access object per l'accesso alla persistenza relativa all'entit?: Entity.
*/
private Dao dao;
public Dao getDao() {
return dao;
}
public void setDao(Dao dao) {
this.dao = dao;
}
/**
* Fornisce l'elenco di tutti gli elementi di tipo Entity presenti nel DB in una
* collection.
*
* @return una collection di Entity presenti nel DB
*/
public Collection listAll() {
return getDao().findAll();
}
/**
* Fornisce l'elenco di tutti gli elementi di tipo Entity presenti nel DB in una
* collection.
*
* @return una collection di Entity presenti nel DB
*/
public Collection listAll(Boolean cacheable) {
return getDao().findAll(cacheable);
}
/**
* Fornisce l'elenco di tutti gli elementi di tipo Entity presenti nel DB in una
* collection.
*
* @return una collection di Entity presenti nel DB
*/
public Collection listAll(Boolean cacheable, Boolean useAcl) {
return getDao().findAll(cacheable, useAcl);
}
/**
* Fornisce l'elenco di tutti gli elementi di tipo Entity presenti nel DB
* corrispondendi ai criteri di ricerca specificati. Gli entity From e To, vengono
* utilizzati come criterio di ricerca seguendo queste regole:
*
* - Per gli attributi testuali viene sempre osservata la sola presenza del valore
* nell'entity From e, se diverso da null, verr? utilizzato come criterio
* "contiene (LIKE)";
* - Per gli attributi numerici e temporali:
*
* - se valorizzato solo l'attributo From verr? utilizzato come criterio
* "maggiore o uguale a";
* - se valorizzato solo l'attributo To verr? utilizzato come criterio
* "minore o uguale a";
* - se valorizzati entrambi gli attributi From e To verr? utilizzato come criterio
* "compreso tra";
*
*
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @return una Collection di Entity. Attenzione, la Collection avr? size 0 se non
* viene trovata alcuna occorrenza.
*/
public Collection search(T theEntityFrom, T theEntityTo) {
return getDao().findByFilter(theEntityFrom, theEntityTo);
}
/**
* Questo metodo estende il servizio offerto dal metodo searchEntity in quanto
* determina i criteri di ricerca in base ad un criteria map specificato in input. Il
* criteria type utilizzato per una determinata propriet? verr? ricercato nel criteria
* map secondo la logica dei bean properties (es. customerId,
* theEntityCategory.categoryDescription, ecc...). Si vedano i tipi definiti nella
* classe CriteriaType per un elenco completo dei criteria definiti.
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @param criteriaMap
* Map di search criteria.
* @return una Collection di Entity. Attenzione, la Collection avr? size 0 se non
* viene trovata alcuna occorrenza.
*/
public Collection searchWithCriteria(T theEntityFrom,
T theEntityTo, Map criteriaMap) {
return getDao().findByFilter(theEntityFrom, theEntityTo, criteriaMap);
}
/**
* Questo metodo estende il servizio offerto dal metodo searchEntity, in quanto
* consente la paginazione dei dati estratti tramite l'indicazione del primo record e
* del numero di records da estrarre.
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @param firstResult
* Primo record da estrarre.
* @param maxResult
* Numero totale di records da estrarre.
* @return una Collection di Entity. Attenzione, la Collection avr? size 0 se non
* viene trovata alcuna occorrenza.
*/
public Collection searchWithPage(T theEntityFrom,
T theEntityTo, int firstResult, int maxResult) {
return getDao().findByFilter(theEntityFrom, theEntityTo, firstResult, maxResult);
}
/**
* Questo metodo aggrega i servizi offerti dai metodi searchEntityWithCriteria e
* searchEntityWithPage in quanto consente sia la paginazione dei dati estratti, sia
* la possibilit? di specificare criteri di ricerca specifici.
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @param criteriaMap
* Map di search criteria.
* @param firstResult
* Primo record da estrarre.
* @param maxResult
* Numero totale di records da estrarre.
* @return una Collection di Entity. Attenzione, la Collection avr? size 0 se non
* viene trovata alcuna occorrenza.
*/
public Collection searchWithPageAndCriteria(T theEntityFrom, T theEntityTo, Map criteriaMap, int firstResult, int maxResult) {
return getDao().findByFilter(theEntityFrom, theEntityTo, criteriaMap, firstResult, maxResult);
}
/**
* Questo metodo estende il servizio offerto dal metodo
* searchEntityWithPageAndCriteria, in quanto aggiunge anche la possibilit? di
* fornire una clausola order by. Inoltre il metodo si presta ad utilizzi con liste
* paginate di dati in quanto restituisce un Map contenente due elementi:
*
* - "list" - contiene la collection dei soli elementi estratti dal DB in base ai
* criteri di ricerca specificati ed alla paginazione;
* - "size" - riporta il numero totale di occorrenze che sarebbero state estratte
* senza l'utilizzo della paginazione.
*
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @param criteriaMap
* Map di search criteria.
* @param firstResult
* Primo record da estrarre.
* @param maxResult
* Numero totale di records da estrarre.
* @param orderBy
* clausola order by.
* @return una HashMap che riporta la collection di elementi estratti per la pagina
* corrente richiesta, pi? il conteggio totale dei records che rispondono ai
* criteri di ricerca specificati, senza tener conto della paginazione.
*/
public Map searchWithCriteriaPagingAndSort(
T theEntityFrom, T theEntityTo,
Map criteriaMap, int firstResult, int maxResult,
String orderBy) {
if (criteriaMap == null) {
criteriaMap = new HashMap();
}
java.util.Map retMap = new HashMap();
Collection list = getDao().findByFilter(theEntityFrom, theEntityTo, criteriaMap, firstResult, maxResult, orderBy);
retMap.put("list", list);
int totRecords = 0;
if (maxResult > 0 && (firstResult > 0 || list.size() == maxResult)) {
totRecords = countWithCriteria(theEntityFrom, theEntityTo, criteriaMap);
} else {
totRecords = list.size();
}
retMap.put("size", new Integer(totRecords));
return retMap;
}
/**
* Questo metodo deve restituisce il conteggio dei records qualificati in base ai
* criteri di ricerca specificati.
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @return Numero totale di records trovati.
*/
public int count(T theEntityFrom, T theEntityTo) {
return getDao().countByFilter(theEntityFrom, theEntityTo);
}
/**
* Questo metodo estende il servizio offerto dal metodo countEntity, in quanto
* determina i criteri di ricerca e conteggio in base ad un criteria map specificato
* in input. Il criteria type da utilizzare per una determinata propriet? verr?
* ricercato nel criteria map secondo la logica dei bean properties (es. customerId,
* theEntityCategory.categoryDescription, ecc...). Si vedano i tipi definiti nella
* classe CriteriaType per un elenco completo dei criteria definiti.
*
* @param theEntityFrom
* Entity {@link Entity} utilizzato come filtro (From).
* @param theEntityTo
* Entity {@link Entity} utilizzato come filtro (To).
* @param criteriaMap
* Map di search criteria.
* @return Numero totale di records trovati.
*/
public int countWithCriteria(T theEntityFrom, T theEntityTo, Map criteriaMap) {
return getDao().countByFilter(theEntityFrom, theEntityTo, criteriaMap);
}
/**
* Questo metodo costruisce un nuovo Entity.
*
* @return Un oggetto Entity inizializzato.
*/
public abstract T newEntity();
/**
* Questo metodo carica e restituisce i dati di dettaglio di un Entity accedendo per
* chiave primaria.
*
*
* @return il riferimento all'oggetto fornito in input, oppure null se non trovato.
*/
public T findByObjectKey(Object objectKey) {
T theEntity = newEntity();
theEntity.setObjectKey(objectKey.toString());
return detail(theEntity);
}
/**
* Questo metodo carica e restituisce i dati di dettaglio di un Entity accedendo per
* chiave primaria.
*
* @param theEntity
* Entity {@link Entity} valorizzato della sola chiave primaria.
*
* @return il riferimento all'oggetto fornito in input, oppure null se non trovato.
*/
public T detail(T theEntity) {
return detail(theEntity, true);
}
/**
* Questo metodo carica e restituisce i dati di dettaglio di un Entity accedendo per
* chiave primaria.
*
* @param theEntity
* Entity {@link Entity} valorizzato della sola chiave primaria.
*
* @return il riferimento all'oggetto fornito in input, oppure null se non trovato.
*/
public T detail(T theEntity, boolean useAcl) {
return getDao().findByPrimaryKey(theEntity, useAcl);
}
/**
* Questo metodo carica e restituisce i dati di dettaglio di un Entity accedendo per
* chiave primaria.
* A differenza del metodo findByPrimaryKey, esso evita la registrazione nella hibernate cache dell'oggetto
* appena letto, consentendo il suo utilizzo per dei check senza per questo incorrere nella noiosissima
* eccezione NonUniqueObjectException di hibernate.
*
* @param theEntity
* Entity {@link Entity} valorizzato della sola chiave primaria.
*
* @return il riferimento all'oggetto fornito in input, oppure null se non trovato.
*/
public T detailNoCache(T theEntity) {
return getDao().findByPrimaryKeyNoCache(theEntity);
}
/**
* Questo metodo controlla l'esistenza di un Entity accedendo per chiave primaria.
*
* @param theEntity
* Entity {@link Entity} valorizzato della sola chiave primaria.
*
* @return true
se l'oggetto ? stato trovato;
* false
se l'oggetto non ? stato trovato.
*/
public boolean exist(T theEntity) {
return getDao().existByPrimaryKey(theEntity);
}
/**
* Questo metodo deve effettua l'inserimento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @return l'Entity {@link Entity} inserita in stato caricato.
*/
public T insert(T theEntity) {
return insert(theEntity, null);
}
/**
* Questo metodo deve effettua l'inserimento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return l'Entity {@link Entity} inserita in stato caricato.
*/
public T insert(T theEntity, String userId) {
return insert(theEntity, userId, null);
}
/**
* Questo metodo deve effettua l'inserimento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return l'Entity {@link Entity} inserita in stato caricato.
*/
public T insert(T theEntity, String userId, EntityDiffAdapter diffAdapter) {
return insert(theEntity, userId, diffAdapter, true, true);
}
/**
* Questo metodo deve effettua l'inserimento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return l'Entity {@link Entity} inserita in stato caricato.
*/
public T insert(T theEntity, String userId, EntityDiffAdapter diffAdapter, boolean checkParentRelation, boolean checkDuplicate) {
if (checkParentRelation) {
checkParentRelation(theEntity);
}
if (checkDuplicate) {
checkDuplicate(theEntity);
}
Differences diffs = NoDifferences.getInstance();
if (diffAdapter != null) {
diffs = computeDifferences(theEntity);
}
T result = getDao().insert(theEntity);
if (!diffs.areEqual()) {
diffAdapter.manageDiff(diffs);
}
return result;
}
/**
* Questo metodo effettua l'aggiornamento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @return true
se l'oggetto ? stato aggiornato correttamente;
* false
se l'oggetto non ? stato aggiornato correttamente.
*/
public T update(T theEntity) {
return update(theEntity, null);
}
/**
* Questo metodo effettua l'aggiornamento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return true
se l'oggetto ? stato aggiornato correttamente;
* false
se l'oggetto non ? stato aggiornato correttamente.
*/
public T update(T theEntity, String userId) {
return update(theEntity, userId, null);
}
/**
* Questo metodo effettua l'aggiornamento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return true
se l'oggetto ? stato aggiornato correttamente;
* false
se l'oggetto non ? stato aggiornato correttamente.
*/
public T update(T theEntity, String userId, EntityDiffAdapter diffAdapter) {
return update(theEntity, userId, diffAdapter, true);
}
/**
* Questo metodo effettua l'aggiornamento di un Entity in base dati.
*
* @param theEntity
* Entity {@link Entity} completamente valorizzato.
* @param userId
* oggetto user.
* @return true
se l'oggetto ? stato aggiornato correttamente;
* false
se l'oggetto non ? stato aggiornato correttamente.
*/
public T update(T theEntity, String userId, EntityDiffAdapter diffAdapter, boolean checkParentRelation) {
if (checkParentRelation) {
checkParentRelation(theEntity);
}
Differences diffs = NoDifferences.getInstance();
if (diffAdapter != null) {
diffs = computeDifferences(theEntity);
}
T result = getDao().update(theEntity);
if (!diffs.areEqual()) {
diffAdapter.manageDiff(diffs);
}
return result;
}
/**
* Questo metodo effettua la cancellazione di un Entity in base dati
*
* @param theEntity
* Entity {@link Entity} valorizzato della sola chiave primaria.
*
* @return true
se l'oggetto ? stato cancellato correttamente;
* false
se l'oggetto non ? stato cancellato correttamente.
*/
public boolean delete(T theEntity) {
return getDao().delete(theEntity);
}
/**
* Metodo che controlla l'esistenza di tutte le entita' padre relazione con l'elemento
* da inserire/aggiornare in base dati. Esso va specializzato da ogni singolo service
* definito.
*
* @param entity
* implementazione dell'entity di cui controllare i riferimenti a padri.
*/
public void checkParentRelation(T entity) {
// Nothing to check since this is a master entity.
}
public void ensureExist(T theEntity, UserMessages userMessages, String entityName) {
if (theEntity != null && !theEntity.isPkNull()) {
if (!exist(theEntity)) {
userMessages.add(new UserMessage("message.genericNotFound", entityName, theEntity.getObjectTitle()));
}
}
}
/**
* Questo metodo controlla l'esistenza in base dati di Entity fornito in input,
* sollevando una BusinessException in caso affermativo.
*
* @param theEntity
* Entity di cui controllarne l'esistenza.
* @throws BusinessException
* nel caso in cui Entity esiste gi? in base dati.
*/
public void checkDuplicate(T theEntity) {
if (theEntity.isPkNotNull() && exist(theEntity)) {
UserMessages userMessages = new UserMessages();
UserMessage msg = new UserMessage("message.genericDupKey", new DefaultMessageSourceResolvable("label.the" + getEntityName(theEntity)), theEntity.getObjectTitle());
userMessages.add(msg);
throw new BusinessException(userMessages);
}
}
/* (non-Javadoc)
* @see it.mice.voila.runtime.service.EntityService#firstElement(java.util.Collection)
*/
public T firstElement(Collection list) {
if (list == null || list.size() == 0) {
return null;
}
return list.iterator().next();
}
/* (non-Javadoc)
* @see it.mice.voila.runtime.service.EntityService#firstElement(java.util.Map)
*/
public T firstElement(Map map) {
if (map == null || map.get("list") == null) {
return null;
}
Collection list = (Collection)map.get("list");
return firstElement(list);
}
private String getEntityName(T theEntity) {
return theEntity.getClass().getSimpleName();
}
public Differences computeDifferences(T theEntity) {
if ((theEntity.getEntityStateDump() != null && theEntity.isChangedEntity()) || (theEntity.getEntityStateDump() == null && theEntity.isNewEntity())) {
T theOldEntity = newEntity();
if (theEntity.getEntityStateDump() != null) {
theOldEntity.setObjectDump(theEntity.getEntityStateDump());
}
return theEntity.diff(theOldEntity);
}
return NoDifferences.getInstance();
}
}