diff --git a/voila-runtime-core/src/main/java/it/mice/voila/runtime/service/GenericEntityService.java b/voila-runtime-core/src/main/java/it/mice/voila/runtime/service/GenericEntityService.java index 0219d368e075c21bec5188f7dff9cbe06c4badd2..acd968a2e2605719bd6058a708cae5ecee134244 100644 --- a/voila-runtime-core/src/main/java/it/mice/voila/runtime/service/GenericEntityService.java +++ b/voila-runtime-core/src/main/java/it/mice/voila/runtime/service/GenericEntityService.java @@ -1,545 +1,545 @@ -package it.mice.voila.runtime.service; - -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; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.pojomatic.Pojomatic; -import org.pojomatic.diff.Differences; -import org.pojomatic.diff.NoDifferences; -import org.springframework.context.MessageSourceResolvable; -import org.springframework.context.support.DefaultMessageSourceResolvable; - -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 - * 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: - *
      - *
    1. se valorizzato solo l'attributo From verrà utilizzato come criterio - * "maggiore o uguale a";
    2. - *
    3. se valorizzato solo l'attributo To verrà utilizzato come criterio - * "minore o uguale a";
    4. - *
    5. se valorizzati entrambi gli attributi From e To verrà utilizzato come criterio - * "compreso tra";
    6. - *
    - *
- * - * @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. - * - * @see #searchEntity(Entity, Entity) - * @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. - * - * @see #searchEntity(Entity, Entity) - * @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. - * - * @see #searchEntityWithCriteria(Entity, Entity, Map) - * @see #searchEntityWithPage(Entity, Entity, int, int) - * @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: - *
    - *
  1. "list" - contiene la collection dei soli elementi estratti dal DB in base ai - * criteri di ricerca specificati ed alla paginazione;
  2. - *
  3. "size" - riporta il numero totale di occorrenze che sarebbero state estratte - * senza l'utilizzo della paginazione.
  4. - *
- * - * @see #searchEntityWithPageAndCriteria(Entity, Entity, Map, int, int) - * @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. - * - * @see #countEntity(Entity, Entity) - * @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.
- * - * @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 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(); - } -} +package it.mice.voila.runtime.service; + +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; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.pojomatic.Pojomatic; +import org.pojomatic.diff.Differences; +import org.pojomatic.diff.NoDifferences; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.support.DefaultMessageSourceResolvable; + +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 + * 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: + *
      + *
    1. se valorizzato solo l'attributo From verrà utilizzato come criterio + * "maggiore o uguale a";
    2. + *
    3. se valorizzato solo l'attributo To verrà utilizzato come criterio + * "minore o uguale a";
    4. + *
    5. se valorizzati entrambi gli attributi From e To verrà utilizzato come criterio + * "compreso tra";
    6. + *
    + *
+ * + * @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. + * + * @see #searchEntity(Entity, Entity) + * @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. + * + * @see #searchEntity(Entity, Entity) + * @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. + * + * @see #searchEntityWithCriteria(Entity, Entity, Map) + * @see #searchEntityWithPage(Entity, Entity, int, int) + * @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: + *
    + *
  1. "list" - contiene la collection dei soli elementi estratti dal DB in base ai + * criteri di ricerca specificati ed alla paginazione;
  2. + *
  3. "size" - riporta il numero totale di occorrenze che sarebbero state estratte + * senza l'utilizzo della paginazione.
  4. + *
+ * + * @see #searchEntityWithPageAndCriteria(Entity, Entity, Map, int, int) + * @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. + * + * @see #countEntity(Entity, Entity) + * @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.
+ * + * @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 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(); + } +} diff --git a/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/dao/impl/DaoHbmGeneric.java b/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/dao/impl/DaoHbmGeneric.java index 4863c5bd8c97cdd50cec63a06de70e2840d6b29d..f74e5e815b1036c7e36bfad687f818676123ac7f 100644 --- a/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/dao/impl/DaoHbmGeneric.java +++ b/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/dao/impl/DaoHbmGeneric.java @@ -1,1128 +1,1134 @@ -package it.mice.voila.runtime.hibernate.dao.impl; - -import it.mice.voila.runtime.dao.CriteriaType; -import it.mice.voila.runtime.dao.Dao; -import it.mice.voila.runtime.dao.SqlCommandOption; -import it.mice.voila.runtime.entity.Entity; -import it.mice.voila.runtime.exception.BusinessException; -import it.mice.voila.runtime.security.SecurityUtils; -import it.mice.voila.runtime.security.UserDetailImpl; -import it.mice.voila.runtime.util.UserMessage; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Timestamp; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.hibernate.FlushMode; -import org.hibernate.Hibernate; -import org.hibernate.ObjectNotFoundException; -import org.hibernate.PropertyValueException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.engine.query.ParamLocationRecognizer; -import org.hibernate.exception.ConstraintViolationException; -import org.springframework.beans.factory.annotation.Autowired; - - -/** - * Created by IntelliJ IDEA. - * User: zzy9v4 - * Date: 2-feb-2007 - * Time: 23.53.04 - * To change this template use File | Settings | File Templates. - */ -public abstract class DaoHbmGeneric implements Dao { - private static final String USER = "user"; - public static final Class[] EMPTY_CLASS_TYPE = {}; - public static final Object[] EMPTY_OBJECT = {}; - public static final String ORDER_BY_CLAUSE = " ORDER BY "; - private static final String COUNT_HQL = "select count(*) "; - /** - * The DOT - */ - protected static final String DOT = "."; - - /** - * Criteria map vuoto. - */ - public static final Map EMPTY_CRITERIA_MAP = new HashMap(); - - /** - * default logger - */ - private static Log logger = LogFactory.getLog(DaoHbmGeneric.class); - - @Autowired - private SessionFactory sessionFactory; - @Autowired - private SqlCommandOption sqlCommandOption; - - private boolean enableNotDeletedEntityFilter = false; - - /** - * Ricerca di un Customer accedendo per chiave primaria.
- * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' - * la chiave primaria, e con essa attiverà la load hibernate che restituirà i dati per - * popolare gli altri campi. - * - * @param theCustomer - * Entity {@link Customer} valorizzato della sola chiave primaria e da - * utilizzare per l'accesso al DB. - * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. - */ - public T findByPrimaryKey(T theEntity) { - return (T) findByPrimaryKey(theEntity, true); - } - - /** - * Ricerca di un Customer accedendo per chiave primaria.
- * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' - * la chiave primaria, e con essa attiverà la load hibernate che restituirà i dati per - * popolare gli altri campi. - * - * @param theCustomer - * Entity {@link Customer} valorizzato della sola chiave primaria e da - * utilizzare per l'accesso al DB. - * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. - */ - public T findByPrimaryKey(T theEntity, boolean useAcl) { - return (T) findByPrimaryKeyInternal(theEntity, useAcl); - } - - /** - * Ricerca di un Customer 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 theCustomer - * Entity {@link Customer} valorizzato della sola chiave primaria e da - * utilizzare per l'accesso al DB. - * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. - */ - public T findByPrimaryKeyNoCache(final T theEntity) { - T filter = theEntity; - try { - filter = (T)theEntity.clone(); - filter.setObjectDump(StringUtils.repeat("null", "|", 200)); - filter.setObjectKey(theEntity.getObjectKey()); - } catch (CloneNotSupportedException e) {} - - Collection result = findByFilter(filter, filter); - if (result.size() == 0) { - return null; - } - if (result.size() > 1) { - throw new IllegalArgumentException("More than one row selected using the following query by template object: " + theEntity); - } - return (T) result.iterator().next(); - } - - - @SuppressWarnings("unchecked") - protected T findByPrimaryKeyInternal(T theEntity, boolean useAcl) { - try { - if (theEntity.isPkNotNull()) { - T loadedObject = (T)getCurrentSession().get(theEntity.getClass(), theEntity); - if (loadedObject != null) { - Set aclQuery = null; - if (useAcl) { - aclQuery = SecurityUtils.extractAclQueries(getEntityName(theEntity), "findByPrimaryKey"); - } - if (!useAcl || aclQuery.size() == 0 || existByPrimaryKey(theEntity)) { - fillParameterEntity(theEntity, loadedObject); - return loadedObject; - } - } - } else { - logger.warn("Unable to load the PK null entity: " + theEntity); - } - return null; - } catch (ObjectNotFoundException e) { - logger.warn("Entity not found: " + theEntity); - return null; - } - } - - /** - * Controlla l'esistenza di un Customer accedendo per chiave primaria.
- * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' - * la chiave primaria, e con essa accederà al db per controllarne l'esistenza. - * - * @param theCustomer - * Entity {@link Customer} valorizzato della sola chiave primaria. - * @return true se l'oggetto Customer è stato trovato;
- * false se l'oggetto Customer non è stato trovato. - */ - public boolean existByPrimaryKey(T theEntity) { - String entityName = getEntityName(theEntity); - StringBuilder sql = new StringBuilder("select 1 from "); - sql.append(StringUtils.capitalize(entityName)).append(" ").append(entityName).append(" WHERE ").append(entityName).append(" = :").append(entityName); - extendTheQueryCriteriaWithAcl(sql, " AND ", entityName, "findByPrimaryKey"); - Query query = getCurrentSession().createQuery(sql.toString()); - query.setEntity(entityName, theEntity); - setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByPrimaryKey"); - return (query.uniqueResult() != null); - } - - public Collection findAll() { - return findAll(Boolean.FALSE); - } - - public Collection findAll(Boolean cacheable) { - String hql = getFromQuery() + getOrderBy(); - return list(getCurrentSession().createQuery(hql).setCacheable(cacheable.booleanValue())); - } - - public T insert(T entity) { - return (T) insertInternal(entity); - } - - public Collection insert(Collection entityList) { - if (entityList != null) { - Iterator i = entityList.iterator(); - while (i.hasNext()) { - // For each entity Customer of the list, - // call insert method if its current status is NEW. - insert(i.next()); - } - } - return entityList; - } - - public T update(T entity) { - return (T) updateInternal(entity); - } - - public Collection update(Collection entityList) { - if (entityList != null) { - Iterator i = entityList.iterator(); - while (i.hasNext()) { - update(i.next()); - } - } - return entityList; - } - - public T store(T entity) { - return saveOrUpdate(entity); - } - - public boolean delete(T entity) { - if (!existByPrimaryKey(entity)) { - return false; - } - try { - deleteInternal(entity); - return true; - } catch (ConstraintViolationException e) { - UserMessage userMessage = new UserMessage("message.genericErrorOnDelete", entity.getClass().getSimpleName()); - throw new BusinessException(userMessage); - } - } - - public boolean delete(Collection entityList) { - if (entityList != null) { - Iterator i = entityList.iterator(); - while (i.hasNext()) { - // For each entity Customer of the list, - // call delete method if its current status is NOT NEW. - if (!delete(i.next())) { - return false; - } - } - } - return true; - } - - public Collection findByFilter(T entityFrom, T entityTo) { - return findByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, buildNewSql(), 0, 0, null); - } - protected abstract String getFromQuery(); - - public Collection findByFilter(T entityFrom, T entityTo, Map criteria) { - return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), 0, 0, null); - } - - public Collection findByFilter(T entityFrom, T entityTo, int firstResult, int maxResult) { - return findByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, buildNewSql(), firstResult, maxResult, null); - } - - public Collection findByFilter(T entityFrom, T entityTo, Map criteria, int firstResult, int maxResult) { - return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), firstResult, maxResult, null); - } - - public Collection findByFilter(T entityFrom, T entityTo, Map criteria, int firstResult, int maxResult, String orderBy) { - return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), firstResult, maxResult, orderBy); - } - - protected StringBuilder buildNewSql() { - return new StringBuilder(getFromQuery()); - } - - public Collection findByFilter(T entityFrom, T entityTo, Map criteria, StringBuilder sql, int firstResult, int maxResult, String orderBy) { - String prefix = " WHERE "; - String entityName = getEntityName(entityFrom); - prefix = extendTheQueryCriteria(entityFrom, entityTo, criteria, sql, prefix, entityName + ".", ""); - extendTheQueryCriteriaWithAcl(sql, prefix, entityName, "findByFilter"); - prepareGroupBy(entityFrom, entityTo, criteria, sql); - sql.append(enhanceOrderByWithPrefix(orderBy, entityName, getOrderBy())); - finalizeFindByFilter(entityFrom, entityTo, criteria, sql); - if (logger.isDebugEnabled()) { - logger.debug("findByFilter: BEAN FROM=" + entityFrom); - logger.debug("findByFilter: BEAN TO=" + entityTo); - logger.debug("findByFilter: SQL=" + sql); - } - Query query = getCurrentSession().createQuery(sql.toString()); - if (maxResult > 0) { - query.setFirstResult(firstResult); - query.setMaxResults(maxResult); - } - setTheStatementFilterForCriteria(entityFrom, entityTo, criteria, query, 0, ""); - setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByFilter"); - return list(query); - } - - protected void prepareGroupBy(T entityFrom, T entityTo, - Map criteria, StringBuilder sql) { - } - - protected void finalizeFindByFilter(T entityFrom, T entityTo, - Map criteria, StringBuilder sql) { - } - - protected void finalizeCountByFilter(T entityFrom, T entityTo, - Map criteria, StringBuilder sql) { - } - - protected abstract String getOrderBy(); - - public abstract String extendTheQueryCriteria(T entityFrom, T entityTo, - Map criteria, StringBuilder sql, String prefix, - String queryPrefix, String criteriaPrefix); - - public abstract int setTheStatementFilterForCriteria(T entityFrom, - T entityTo, Map criteria, Query query, int counter, - String criteriaPrefix); - - - public String extendTheQueryCriteriaWithAcl(StringBuilder sql, String prefix, String entityName, String queryName) { - - Set aclQueries = SecurityUtils.extractAclQueries(entityName, queryName); - if (aclQueries.size() > 0) { - String or = ""; - sql.append(prefix).append(" ("); - for (Iterator iterator = aclQueries.iterator(); iterator.hasNext();) { - String aclQuery = (String) iterator.next(); - sql.append(or).append(aclQuery); - or = " OR "; - } - sql.append(") "); - prefix = "AND "; - } - return prefix; - } - - public void setTheStatementFilterForCriteriaWithAcl(Query query, String entityName, String queryId) { - - Set aclQueries = SecurityUtils.extractAclQueries(entityName, queryId); - if (aclQueries.size() > 0) { - for (Iterator iterator = aclQueries.iterator(); iterator.hasNext();) { - String aclQuery = (String) iterator.next(); - ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( aclQuery ); - Iterator itr = recognizer.getNamedParameterDescriptionMap().entrySet().iterator(); - UserDetailImpl userDetailImpl = (UserDetailImpl)SecurityUtils.getCurrentUserDetail(); - Properties p = userDetailImpl.getUserChainProperties(); - while( itr.hasNext() ) { - Map.Entry entry = ( Map.Entry ) itr.next(); - String name = ( String ) entry.getKey(); - Object value = determineType(p.getProperty(name)); - if (value == null) { - try { - value = PropertyUtils.getProperty(userDetailImpl, name.replaceAll("\\_", ".")); - } catch (Exception e) { - e.printStackTrace(); - } - } - query.setParameter(name, value); - } - } - } - } - - private Object determineType(String value) { - if (value == null) { - return value; - } - if (value.startsWith("\"") || value.startsWith("'")) { - return value; - } - try { - return Integer.parseInt(value); - } catch (Exception e) { - return value; - } - } - - public int countByFilter(T entityFrom, T entityTo) { - return countByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, getCountQuery()); - } - - public int countByFilter(T entityFrom, T entityTo, Map criteria) { - return countByFilter(entityFrom, entityTo, criteria, getCountQuery()); - } - - public StringBuilder getCountQuery() { - return new StringBuilder(COUNT_HQL + getCountFromQuery()); - } - - /** - * Restituisce la clausola iniziale per la costruzione di HQL Query. - * - * @return la clausola iniziale per la costruzione di HQL Query. - * @see it.mice.voila.runtime.hibernate.dao.impl.DaoHbmGeneric#getFromQuery() - */ - protected String getCountFromQuery() { - return getFromQuery(); - } - - public int countByFilter(T entityFrom, T entityTo, Map criteria, StringBuilder sql) { - String entityName = getEntityName(entityFrom); - String prefix = " WHERE "; - - prefix = extendTheQueryCriteria(entityFrom, entityTo, criteria, sql, prefix, entityName + ".", ""); - extendTheQueryCriteriaWithAcl(sql, prefix, entityName, "findByFilter"); -// prepareGroupBy(entityFrom, entityTo, criteria, sql); - finalizeCountByFilter(entityFrom, entityTo, criteria, sql); - - Query query = getCurrentSession().createQuery(sql.toString()); - setTheStatementFilterForCriteria(entityFrom, entityTo, criteria, query, 0, ""); - setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByFilter"); - Long totRecords = (Long) query.uniqueResult(); - if (logger.isDebugEnabled()) { - logger.debug("countByFilter: BEAN FROM=" + entityFrom); - logger.debug("countByFilter: BEAN TO=" + entityTo); - logger.debug("countByFilter: SQL=" + sql); - logger.debug("countByFilter: Num of records=" + totRecords); - } - return totRecords.intValue(); - } - - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - public void setSessionFactory(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - public Session getCurrentSession() { - Session retSession = getSessionFactory().getCurrentSession(); - if (isEnableNotDeletedEntityFilter()) { - retSession.enableFilter("notDeletedEntities"); - } - retSession.setFlushMode(FlushMode.parse(getSqlCommandOption().getFlushMode())); - return retSession; - } - - public SqlCommandOption getSqlCommandOption() { - return sqlCommandOption; - } - - public void setSqlCommandOption(SqlCommandOption sqlCommandOption) { - this.sqlCommandOption = sqlCommandOption; - } - - public boolean isEnableNotDeletedEntityFilter() { - return enableNotDeletedEntityFilter; - } - - public void setEnableNotDeletedEntityFilter(boolean enableNotDeletedEntityFilter) { - this.enableNotDeletedEntityFilter = enableNotDeletedEntityFilter; - } - - public java.sql.Timestamp getCurrentTimestamp() - { - return new java.sql.Timestamp(System.currentTimeMillis()); - } - - private void fillParameterEntity(T parameterEntity, T loadedObject) { - evictIfNecessary(loadedObject); - if (loadedObject != parameterEntity) { - if (logger.isInfoEnabled()) { - logger.info("Found a duplicated object with the same identifier in the hibernate session. Try to resolve aniway. Please check results !"); - } - parameterEntity.setInternalEntityStateToLoaded(); - parameterEntity.setObjectDump(loadedObject.getObjectDump()); - parameterEntity.setInternalEntityStateToLoaded(); - } - } - - public T insertInternal(T theEntity) { - if (!theEntity.isNewEntity()) { - if (logger.isDebugEnabled()) { - logger.debug("Operation 'insert' discarded because the entity is not in new internal status: " + theEntity); - } - return theEntity; - } - - getCurrentSession().save(theEntity); - flushIfNecessary(); - if (logger.isDebugEnabled()) { - logger.debug("insert -> success: " + theEntity); - } - evictIfNecessary(theEntity); - return theEntity; - } - - public T updateInternal(T theEntity) { - clearSessionBeforeUpdateIfNecessary(); - getCurrentSession().update(theEntity); - flushIfNecessary(); - if (logger.isDebugEnabled()) { - logger.debug("update -> success: " + theEntity); - } - evictIfNecessary(theEntity); - return theEntity; - } - - public void deleteInternal(T theEntity) { - try { - getCurrentSession().delete(theEntity); - } catch (PropertyValueException e) { - if (logger.isWarnEnabled()) { - logger.warn("Exception trying to delete an entity, try to load it before retry deletion..."); - } - getCurrentSession().evict(theEntity); - T entityToDelete = findByPrimaryKeyNoCache(theEntity); - entityToDelete.setInternalEntityStateToDeleted(); - getCurrentSession().delete(entityToDelete); - } - flushIfNecessary(); - if (logger.isDebugEnabled()) { - logger.debug("delete -> success: " + theEntity); - } - evictIfNecessary(theEntity); - } - - public Collection list(Query query) { - Collection result = query.list(); - if (getSqlCommandOption().isEvictHibernateListElementImmediatly()) { - Iterator resultIt = result.iterator(); - while (resultIt.hasNext()) { - T element = (T) resultIt.next(); - evictListElementIfNecessary(element); - } - } - return result; - } - - public T saveOrUpdate(T theEntity) { - if (theEntity.isChangedEntity()) { - return updateInternal(theEntity); - } - if (theEntity.isNewEntity()) { - return insertInternal(theEntity); - } - if (logger.isDebugEnabled()) { - logger.debug("Operation 'saveOrUpdate' discarded because the entity is not in new or changed internal status: " + theEntity); - } - return theEntity; - } - - private void flushIfNecessary() { - if (getSqlCommandOption().isFlushHibernateSessionImmediatly()) { - getCurrentSession().flush(); - if (logger.isDebugEnabled()) { - logger.debug("Flushing entity immediatly."); - } - } - } - - private void clearSessionBeforeUpdateIfNecessary() { - if (getSqlCommandOption().isClearHibernateSessionBeforeUpdate()) { - getCurrentSession().clear(); - if (logger.isDebugEnabled()) { - logger.debug("Clear hibernate session before update command execution."); - } - } - } - - private void evictIfNecessary(T theEntity) { - if (getSqlCommandOption().isEvictHibernateElementImmediatly()) { - getCurrentSession().evict(theEntity); - if (logger.isDebugEnabled()) { - logger.debug("Evict entity immediatly."); - } - } - } - - /** - * Evict all object list if evictHibernateListElement is set to true in applicationDAO - * @param theEntity - */ - private void evictListElementIfNecessary(T theEntity) { - getCurrentSession().evict(theEntity); - if (logger.isDebugEnabled()) { - logger.debug("Evict list entity element immediatly."); - } - - } - - protected String extendQueryCriteria(StringBuilder sql, String prefix, Object valueFrom, Object valueTo, String parameterName, Object criteriaType) { - return extendQueryCriteria(sql, prefix, valueFrom, valueTo, parameterName, criteriaType, true); - } - - protected String extendQueryCriteria(StringBuilder sql, String prefix, Object valueFrom, Object valueTo, String parameterName, Object criteriaType, boolean useUpper) { - - criteriaType = convertCriteriaToByte(criteriaType); - - if (criteriaType == CriteriaType.DEFAULT && valueFrom instanceof String && valueFrom != null && valueFrom.equals(valueTo)) { - criteriaType = CriteriaType.EQUALS; - } - - if (criteriaType == CriteriaType.DEFAULT) { - if (valueFrom instanceof String) { - return appendToFilterLike(sql, prefix, valueFrom, parameterName, useUpper); - } else { - return appendToFilterFromTo(sql, prefix, valueFrom, valueTo, parameterName); - } - } - - if (criteriaType.equals(CriteriaType.NONE)) { - return prefix; - } - - if (criteriaType.equals(CriteriaType.EQUALS)) { - if (valueFrom != null) { - if (valueFrom instanceof String) { - sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(parameterName, useUpper)).append(" = ?"); - } else { - sql.append(prefix).append(parameterName).append(" = ?"); - } - prefix = " AND "; - } - return prefix; - } - - if (criteriaType.equals(CriteriaType.NOTEQUALS)) { - if (valueFrom != null) { - if (valueFrom instanceof String) { - sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(parameterName, useUpper)).append(" != ?"); - } else { - sql.append(prefix).append(parameterName).append(" != ?"); - } - prefix = " AND "; - } - return prefix; - } - - if (criteriaType.equals(CriteriaType.IS_NULL)) { - sql.append(prefix).append(parameterName).append(" IS NULL "); - prefix = " AND "; - return prefix; - } - - if (criteriaType.equals(CriteriaType.IS_NOT_NULL)) { - sql.append(prefix).append(parameterName).append(" IS NOT NULL "); - prefix = " AND "; - return prefix; - } - - if (criteriaType.equals(CriteriaType.STARTWITH) || criteriaType.equals(CriteriaType.ENDWITH) || criteriaType.equals(CriteriaType.CONTAINS)) - { - return appendToFilterLike(sql, prefix, valueFrom, parameterName, useUpper); - } - - if (criteriaType.equals(CriteriaType.NOT_STARTWITH) || criteriaType.equals(CriteriaType.NOT_ENDWITH) || criteriaType.equals(CriteriaType.NOT_CONTAINS)) - { - return appendToFilterNotLike(sql, prefix, valueFrom, parameterName, useUpper); - } - - if (criteriaType.equals(CriteriaType.GREATER_OR_EQUAL_THAN)) { - return appendToFilterFromTo(sql, prefix, valueFrom, null, parameterName); - } - - if (criteriaType.equals(CriteriaType.LESS_OR_EQUAL_THAN)) { - return appendToFilterFromTo(sql, prefix, null, valueFrom, parameterName); - } - - if (criteriaType.equals(CriteriaType.BETWEEN)) { - return appendToFilterFromTo(sql, prefix, valueFrom, valueTo, parameterName); - } - - if (criteriaType.equals(CriteriaType.NOT_BETWEEN)) { - return appendToFilterNotBetween(sql, prefix, valueFrom, valueTo, parameterName); - } - - if (criteriaType instanceof CriteriaType.InClause) { - Object listValue = ((CriteriaType.InClause)criteriaType).getListValue(); - return appendToFilterIn(sql, prefix, listValue, parameterName); - } - - if (criteriaType instanceof CriteriaType.NotInClause) { - Object listValue = ((CriteriaType.NotInClause)criteriaType).getListValue(); - return appendToFilterNotIn(sql, prefix, listValue, parameterName); - } - - logger.warn("Unrecognized criteria type: " + criteriaType + ". Check your query. Filter discarded !"); - return prefix; - } - - protected int setStatementFilterForCriteria(Query query, int counter, Object valueFrom, Object valueTo, Object criteriaType) { - return setStatementFilterForCriteria(query, counter, valueFrom, valueTo, criteriaType, true); - } - - protected int setStatementFilterForCriteria(Query query, int counter, Object valueFrom, Object valueTo, Object criteriaType, boolean useUpper) { - criteriaType = convertCriteriaToByte(criteriaType); - - if (criteriaType == CriteriaType.DEFAULT && valueFrom instanceof String && valueFrom != null && valueFrom.equals(valueTo)) { - criteriaType = CriteriaType.EQUALS; - } - - if (criteriaType == CriteriaType.DEFAULT) { - if (valueFrom instanceof String) { - return setStatementFilterLike( - query, - counter, - valueFrom, - useUpper - ); - } else { - return setStatementFilterFromTo( - query, - counter, - valueFrom, - valueTo - ); - } - } - - if (criteriaType.equals(CriteriaType.NONE) || criteriaType.equals(CriteriaType.IS_NULL) || criteriaType.equals(CriteriaType.IS_NOT_NULL)) { - return counter; - } - - if (criteriaType.equals(CriteriaType.EQUALS) || criteriaType.equals(CriteriaType.NOTEQUALS)) { - return setStatementFilter(query, counter, valueFrom, useUpper); - } - - if (criteriaType.equals(CriteriaType.STARTWITH) || criteriaType.equals(CriteriaType.NOT_STARTWITH)) { - return setStatementFilterLike(query, counter, valueFrom, "", "%", useUpper); - } - - if (criteriaType.equals(CriteriaType.ENDWITH) || criteriaType.equals(CriteriaType.NOT_ENDWITH)) { - return setStatementFilterLike(query, counter, valueFrom, "%", "", useUpper); - } - - if (criteriaType.equals(CriteriaType.CONTAINS) || criteriaType.equals(CriteriaType.NOT_CONTAINS)) { - return setStatementFilterLike(query, counter, valueFrom, "%", "%", useUpper); - } - - if (criteriaType.equals(CriteriaType.GREATER_OR_EQUAL_THAN)) { - return setStatementFilterFromTo( - query, - counter, - valueFrom, - null - ); - } - - if (criteriaType.equals(CriteriaType.LESS_OR_EQUAL_THAN)) { - return setStatementFilterFromTo( - query, - counter, - null, - valueFrom - ); - } - - if (criteriaType.equals(CriteriaType.BETWEEN) || criteriaType.equals(CriteriaType.NOT_BETWEEN)) { - return setStatementFilterFromTo( - query, - counter, - valueFrom, - valueTo - ); - } - - if (criteriaType instanceof CriteriaType.InClause) { - Object listValue = ((CriteriaType.InClause)criteriaType).getListValue(); - return setStatementFilterIn(query, counter, listValue); - } - - if (criteriaType instanceof CriteriaType.NotInClause) { - Object listValue = ((CriteriaType.NotInClause)criteriaType).getListValue(); - return setStatementFilterIn(query, counter, listValue); - } - - logger.warn("Unrecognized criteria type: " + criteriaType + ". Check your query. Filter discarded !"); - return counter; - } - - protected String appendToFilterLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName) { - return appendToFilterLike(sql, prefix, fieldFrom, columnName, true); - } - - protected String appendToFilterLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName, boolean useUpper) { - if (fieldFrom != null) { - sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(columnName, useUpper)).append(" LIKE ?"); - prefix = " AND "; - } - return prefix; - } - - protected String appendToFilterNotLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName) { - return appendToFilterNotLike(sql, prefix, fieldFrom, columnName, true); - } - - protected String appendToFilterNotLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName, boolean useUpper) { - if (fieldFrom != null) { - sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(columnName, useUpper)).append(" NOT LIKE ?"); - prefix = " AND "; - } - return prefix; - } - - protected String appendToFilterIn(StringBuilder sql, String prefix, Object array, String columnName) { - return appendToFilterIn(sql, prefix, array, columnName, false); - } - - protected String appendToFilterNotIn(StringBuilder sql, String prefix, Object array, String columnName) { - return appendToFilterIn(sql, prefix, array, columnName, true); - } - - protected String appendToFilterIn(StringBuilder sql, String prefix, Object array, String columnName, boolean useNot) { - if (array != null) { - if (useNot) { - sql.append(prefix).append(columnName).append(" NOT IN ("); - } else { - sql.append(prefix).append(columnName).append(" IN ("); - } - if (array instanceof Object[]) { - Object[] target = (Object[])array; - String delimiter = ""; - for (int i=0; i= ?"); - prefix = " AND "; - } - if (fieldFrom == null && fieldTo != null) { - sql.append(prefix).append(columnName).append(" <= ?"); - prefix = " AND "; - } - return prefix; - } - - protected String appendToFilterNotBetween(StringBuilder sql, String prefix, Object fieldFrom, Object fieldTo, String columnName) { - sql.append(prefix).append(columnName).append(" NOT BETWEEN ? AND ?"); - prefix = " AND "; - return prefix; - } - - /** - * @param query - * @param counter - * @param fieldFrom - */ - protected int setStatementFilterFromTo(Query query, int counter, Object fieldFrom, Object fieldTo) { - if (fieldFrom != null && fieldTo != null) { - setStatementFilter(query, counter++, fieldFrom); - if (!fieldFrom.equals(fieldTo)) { - setStatementFilter(query, counter++, fieldTo); - } - } - if (fieldFrom != null && fieldTo == null) { - setStatementFilter(query, counter++, fieldFrom); - } - if (fieldFrom == null && fieldTo != null) { - setStatementFilter(query, counter++, fieldTo); - } - return counter; - } - - /** - * @param query - * @param counter - * @param fieldFrom - */ - protected int setStatementFilter(Query query, int counter, Object fieldFrom) { - return setStatementFilter(query, counter, fieldFrom, true); - } - protected int setStatementFilter(Query query, int counter, Object fieldFrom, boolean useUpper) { - if (fieldFrom != null) { - if (fieldFrom instanceof String) { - if (getSqlCommandOption().isLikeFilterIgnoreCase() && useUpper) { - if (logger.isDebugEnabled()) { - logger.debug("Setting String parameter number " + counter + " to value <" + ((String) fieldFrom).toUpperCase() + ">"); - } - query.setString(counter++, ((String) fieldFrom).toUpperCase()); - } else { - if (logger.isDebugEnabled()) { - logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setString(counter++, ((String) fieldFrom)); - } - } else if (fieldFrom instanceof java.sql.Timestamp) { - if (logger.isDebugEnabled()) { - logger.debug("Setting Timestamp parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setTimestamp(counter++, (Timestamp) fieldFrom); - } else if (fieldFrom instanceof java.util.Date) { - if (logger.isDebugEnabled()) { - logger.debug("Setting java.util.Date parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setDate(counter++, (Date) fieldFrom); - } else if (fieldFrom instanceof java.sql.Date) { - if (logger.isDebugEnabled()) { - logger.debug("Setting java.sql.Date parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setDate(counter++, (java.sql.Date) fieldFrom); - } else if (fieldFrom instanceof java.lang.Number) { - if (logger.isDebugEnabled()) { - logger.debug("Setting Double parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setDouble(counter++, ((Number) fieldFrom).doubleValue()); - } else if (fieldFrom instanceof java.lang.Boolean) { - if (logger.isDebugEnabled()) { - logger.debug("Setting Boolean parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setBoolean(counter++, ((Boolean) fieldFrom).booleanValue()); - } - } - return counter; - } - - /** - * @param query - * @param counter - * @param fieldFrom - */ - protected int setStatementFilterLike(Query query, int counter, Object fieldFrom) { - return setStatementFilterLike(query, counter, fieldFrom, true); - } - - protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, boolean useUpper) { - if (fieldFrom != null) { - if (fieldFrom instanceof String) { - if (logger.isDebugEnabled()) { - logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setString(counter++, sqlCommandOption.getStatementFilterLike((String) fieldFrom, useUpper)); - } - } - return counter; - } - - protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, String likeFilterMethodLeftSymbolParam, String likeFilterMethodRightSymbolParam) { - return setStatementFilterLike(query, counter, fieldFrom, likeFilterMethodLeftSymbolParam, likeFilterMethodRightSymbolParam, true); - } - - protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, String likeFilterMethodLeftSymbolParam, String likeFilterMethodRightSymbolParam, boolean useUpper) { - if (fieldFrom != null) { - if (logger.isDebugEnabled()) { - logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); - } - query.setString(counter++, sqlCommandOption.getStatementFilterLike(fieldFrom.toString(), likeFilterMethodLeftSymbolParam, likeFilterMethodRightSymbolParam, useUpper)); - } - return counter; - } - - protected int setStatementFilterIn(Query query, int counter, Object array) { - if (array != null) { - if (array instanceof Object[]) { - Object[] target = (Object[])array; - for (int i=0; i"); - } - query.setParameter(counter++, target[i]); - } - } - if (array instanceof Collection) { - Iterator i = ((Collection)array).iterator(); - while (i.hasNext()) { - Object parm = i.next(); - if (logger.isDebugEnabled()) { - logger.debug("Setting IN parameter number " + counter + " to value <" + parm + ">"); - } - query.setParameter(counter++, parm); - } - } - } - return counter; - } - - protected String enhanceOrderByWithPrefix(String orderBy, String prefix, String defaultOrderBy) { - if (orderBy == null || orderBy.trim().length() == 0) { - return defaultOrderBy; - } - - StringBuilder result = new StringBuilder(" ORDER BY "); - String delimiter = ""; - String[] orderKeys = orderBy.split(","); - for (int i=0; iBlob object from a byte array using the - * hibernate specific implementation. The returned object will be initially - * immutable. - * - * @param bytes a byte array - * @return the Blob object - */ - public Blob createBlob(byte[] bytes) { - return Hibernate.createBlob(bytes); - } - - /** - * Utility method to create a Blob object from an InputStram using the - * hibernate specific implementation. The returned object will be initially - * immutable. - * - * @param stream a binary stream - * @return the Blob object - * @throws IOException - */ - public Blob createBlob(InputStream stream) throws IOException { - return Hibernate.createBlob(stream); - } - - /** - * Utility method to create a Blob object from an InputStram using the - * hibernate specific implementation. The returned object will be initially - * immutable. - * - * @param stream a binary stream - * @param length the number of bytes in the stream - * @return the Blob object - */ - public Blob createBlob(InputStream stream, int length) { - return Hibernate.createBlob(stream, length); - } - - public Object getCriteriaObject(Map criteria, String name) { - return criteria.get(name); - } - - public boolean hasCriteria(Map criteria, String name) { - return !StringUtils.isEmpty(getCriteriaAsString(criteria, name)); - } - - public String getCriteriaAsString(Map criteria, String name) { - Object result = getCriteriaObject(criteria, name); - if (result != null) { - return result.toString(); - } - return null; - } - - protected Collection findByParent(String fromQuery, String entityName, String parentEntityName, Entity parentEntity, String operationName) { - StringBuilder sql = new StringBuilder(fromQuery); - sql.append(" WHERE ").append(entityName).append(".").append(parentEntityName).append(" = :").append(parentEntityName); - extendTheQueryCriteriaWithAcl(sql, " AND ", entityName, operationName); - sql.append(getOrderBy()); - Query query = getCurrentSession().createQuery(sql.toString()); - query.setParameter(parentEntityName, parentEntity); - setTheStatementFilterForCriteriaWithAcl(query, entityName, operationName); - return list(query); - } -} +package it.mice.voila.runtime.hibernate.dao.impl; + +import it.mice.voila.runtime.dao.CriteriaType; +import it.mice.voila.runtime.dao.Dao; +import it.mice.voila.runtime.dao.SqlCommandOption; +import it.mice.voila.runtime.entity.Entity; +import it.mice.voila.runtime.exception.BusinessException; +import it.mice.voila.runtime.security.SecurityUtils; +import it.mice.voila.runtime.security.UserDetailImpl; +import it.mice.voila.runtime.util.UserMessage; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.FlushMode; +import org.hibernate.Hibernate; +import org.hibernate.HibernateException; +import org.hibernate.ObjectNotFoundException; +import org.hibernate.PropertyValueException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.StaleObjectStateException; +import org.hibernate.engine.query.ParamLocationRecognizer; +import org.hibernate.exception.ConstraintViolationException; +import org.springframework.beans.factory.annotation.Autowired; + + +/** + * Created by IntelliJ IDEA. + * User: zzy9v4 + * Date: 2-feb-2007 + * Time: 23.53.04 + * To change this template use File | Settings | File Templates. + */ +public abstract class DaoHbmGeneric implements Dao { + private static final String USER = "user"; + public static final Class[] EMPTY_CLASS_TYPE = {}; + public static final Object[] EMPTY_OBJECT = {}; + public static final String ORDER_BY_CLAUSE = " ORDER BY "; + private static final String COUNT_HQL = "select count(*) "; + /** + * The DOT + */ + protected static final String DOT = "."; + + /** + * Criteria map vuoto. + */ + public static final Map EMPTY_CRITERIA_MAP = new HashMap(); + + /** + * default logger + */ + private static Log logger = LogFactory.getLog(DaoHbmGeneric.class); + + @Autowired + private SessionFactory sessionFactory; + @Autowired + private SqlCommandOption sqlCommandOption; + + private boolean enableNotDeletedEntityFilter = false; + + /** + * Ricerca di un Customer accedendo per chiave primaria.
+ * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' + * la chiave primaria, e con essa attiverà la load hibernate che restituirà i dati per + * popolare gli altri campi. + * + * @param theCustomer + * Entity {@link Customer} valorizzato della sola chiave primaria e da + * utilizzare per l'accesso al DB. + * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. + */ + public T findByPrimaryKey(T theEntity) { + return (T) findByPrimaryKey(theEntity, true); + } + + /** + * Ricerca di un Customer accedendo per chiave primaria.
+ * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' + * la chiave primaria, e con essa attiverà la load hibernate che restituirà i dati per + * popolare gli altri campi. + * + * @param theCustomer + * Entity {@link Customer} valorizzato della sola chiave primaria e da + * utilizzare per l'accesso al DB. + * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. + */ + public T findByPrimaryKey(T theEntity, boolean useAcl) { + return (T) findByPrimaryKeyInternal(theEntity, useAcl); + } + + /** + * Ricerca di un Customer 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 theCustomer + * Entity {@link Customer} valorizzato della sola chiave primaria e da + * utilizzare per l'accesso al DB. + * @return il riferimento all'oggetto fornito in input, oppure null se non trovato. + */ + public T findByPrimaryKeyNoCache(final T theEntity) { + T filter = theEntity; + try { + filter = (T)theEntity.clone(); + filter.setObjectDump(StringUtils.repeat("null", "|", 200)); + filter.setObjectKey(theEntity.getObjectKey()); + } catch (CloneNotSupportedException e) {} + + Collection result = findByFilter(filter, filter); + if (result.size() == 0) { + return null; + } + if (result.size() > 1) { + throw new IllegalArgumentException("More than one row selected using the following query by template object: " + theEntity); + } + return (T) result.iterator().next(); + } + + + @SuppressWarnings("unchecked") + protected T findByPrimaryKeyInternal(T theEntity, boolean useAcl) { + try { + if (theEntity.isPkNotNull()) { + T loadedObject = (T)getCurrentSession().get(theEntity.getClass(), theEntity); + if (loadedObject != null) { + Set aclQuery = null; + if (useAcl) { + aclQuery = SecurityUtils.extractAclQueries(getEntityName(theEntity), "findByPrimaryKey"); + } + if (!useAcl || aclQuery.size() == 0 || existByPrimaryKey(theEntity)) { + fillParameterEntity(theEntity, loadedObject); + return loadedObject; + } + } + } else { + logger.warn("Unable to load the PK null entity: " + theEntity); + } + return null; + } catch (ObjectNotFoundException e) { + logger.warn("Entity not found: " + theEntity); + return null; + } + } + + /** + * Controlla l'esistenza di un Customer accedendo per chiave primaria.
+ * Il metodo prende in input l'oggetto di tipo {@link Customer} dal quale prelevera' + * la chiave primaria, e con essa accederà al db per controllarne l'esistenza. + * + * @param theCustomer + * Entity {@link Customer} valorizzato della sola chiave primaria. + * @return true se l'oggetto Customer è stato trovato;
+ * false se l'oggetto Customer non è stato trovato. + */ + public boolean existByPrimaryKey(T theEntity) { + String entityName = getEntityName(theEntity); + StringBuilder sql = new StringBuilder("select 1 from "); + sql.append(StringUtils.capitalize(entityName)).append(" ").append(entityName).append(" WHERE ").append(entityName).append(" = :").append(entityName); + extendTheQueryCriteriaWithAcl(sql, " AND ", entityName, "findByPrimaryKey"); + Query query = getCurrentSession().createQuery(sql.toString()); + query.setEntity(entityName, theEntity); + setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByPrimaryKey"); + return (query.uniqueResult() != null); + } + + public Collection findAll() { + return findAll(Boolean.FALSE); + } + + public Collection findAll(Boolean cacheable) { + String hql = getFromQuery() + getOrderBy(); + return list(getCurrentSession().createQuery(hql).setCacheable(cacheable.booleanValue())); + } + + public T insert(T entity) { + return (T) insertInternal(entity); + } + + public Collection insert(Collection entityList) { + if (entityList != null) { + Iterator i = entityList.iterator(); + while (i.hasNext()) { + // For each entity Customer of the list, + // call insert method if its current status is NEW. + insert(i.next()); + } + } + return entityList; + } + + public T update(T entity) { + return (T) updateInternal(entity); + } + + public Collection update(Collection entityList) { + if (entityList != null) { + Iterator i = entityList.iterator(); + while (i.hasNext()) { + update(i.next()); + } + } + return entityList; + } + + public T store(T entity) { + return saveOrUpdate(entity); + } + + public boolean delete(T entity) { + if (!existByPrimaryKey(entity)) { + return false; + } + try { + deleteInternal(entity); + return true; + } catch (ConstraintViolationException e) { + UserMessage userMessage = new UserMessage("message.genericErrorOnDelete", entity.getClass().getSimpleName()); + throw new BusinessException(userMessage); + } + } + + public boolean delete(Collection entityList) { + if (entityList != null) { + Iterator i = entityList.iterator(); + while (i.hasNext()) { + // For each entity Customer of the list, + // call delete method if its current status is NOT NEW. + if (!delete(i.next())) { + return false; + } + } + } + return true; + } + + public Collection findByFilter(T entityFrom, T entityTo) { + return findByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, buildNewSql(), 0, 0, null); + } + protected abstract String getFromQuery(); + + public Collection findByFilter(T entityFrom, T entityTo, Map criteria) { + return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), 0, 0, null); + } + + public Collection findByFilter(T entityFrom, T entityTo, int firstResult, int maxResult) { + return findByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, buildNewSql(), firstResult, maxResult, null); + } + + public Collection findByFilter(T entityFrom, T entityTo, Map criteria, int firstResult, int maxResult) { + return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), firstResult, maxResult, null); + } + + public Collection findByFilter(T entityFrom, T entityTo, Map criteria, int firstResult, int maxResult, String orderBy) { + return findByFilter(entityFrom, entityTo, criteria, buildNewSql(), firstResult, maxResult, orderBy); + } + + protected StringBuilder buildNewSql() { + return new StringBuilder(getFromQuery()); + } + + public Collection findByFilter(T entityFrom, T entityTo, Map criteria, StringBuilder sql, int firstResult, int maxResult, String orderBy) { + String prefix = " WHERE "; + String entityName = getEntityName(entityFrom); + prefix = extendTheQueryCriteria(entityFrom, entityTo, criteria, sql, prefix, entityName + ".", ""); + extendTheQueryCriteriaWithAcl(sql, prefix, entityName, "findByFilter"); + prepareGroupBy(entityFrom, entityTo, criteria, sql); + sql.append(enhanceOrderByWithPrefix(orderBy, entityName, getOrderBy())); + finalizeFindByFilter(entityFrom, entityTo, criteria, sql); + if (logger.isDebugEnabled()) { + logger.debug("findByFilter: BEAN FROM=" + entityFrom); + logger.debug("findByFilter: BEAN TO=" + entityTo); + logger.debug("findByFilter: SQL=" + sql); + } + Query query = getCurrentSession().createQuery(sql.toString()); + if (maxResult > 0) { + query.setFirstResult(firstResult); + query.setMaxResults(maxResult); + } + setTheStatementFilterForCriteria(entityFrom, entityTo, criteria, query, 0, ""); + setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByFilter"); + return list(query); + } + + protected void prepareGroupBy(T entityFrom, T entityTo, + Map criteria, StringBuilder sql) { + } + + protected void finalizeFindByFilter(T entityFrom, T entityTo, + Map criteria, StringBuilder sql) { + } + + protected void finalizeCountByFilter(T entityFrom, T entityTo, + Map criteria, StringBuilder sql) { + } + + protected abstract String getOrderBy(); + + public abstract String extendTheQueryCriteria(T entityFrom, T entityTo, + Map criteria, StringBuilder sql, String prefix, + String queryPrefix, String criteriaPrefix); + + public abstract int setTheStatementFilterForCriteria(T entityFrom, + T entityTo, Map criteria, Query query, int counter, + String criteriaPrefix); + + + public String extendTheQueryCriteriaWithAcl(StringBuilder sql, String prefix, String entityName, String queryName) { + + Set aclQueries = SecurityUtils.extractAclQueries(entityName, queryName); + if (aclQueries.size() > 0) { + String or = ""; + sql.append(prefix).append(" ("); + for (Iterator iterator = aclQueries.iterator(); iterator.hasNext();) { + String aclQuery = (String) iterator.next(); + sql.append(or).append(aclQuery); + or = " OR "; + } + sql.append(") "); + prefix = "AND "; + } + return prefix; + } + + public void setTheStatementFilterForCriteriaWithAcl(Query query, String entityName, String queryId) { + + Set aclQueries = SecurityUtils.extractAclQueries(entityName, queryId); + if (aclQueries.size() > 0) { + for (Iterator iterator = aclQueries.iterator(); iterator.hasNext();) { + String aclQuery = (String) iterator.next(); + ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocations( aclQuery ); + Iterator itr = recognizer.getNamedParameterDescriptionMap().entrySet().iterator(); + UserDetailImpl userDetailImpl = (UserDetailImpl)SecurityUtils.getCurrentUserDetail(); + Properties p = userDetailImpl.getUserChainProperties(); + while( itr.hasNext() ) { + Map.Entry entry = ( Map.Entry ) itr.next(); + String name = ( String ) entry.getKey(); + Object value = determineType(p.getProperty(name)); + if (value == null) { + try { + value = PropertyUtils.getProperty(userDetailImpl, name.replaceAll("\\_", ".")); + } catch (Exception e) { + e.printStackTrace(); + } + } + query.setParameter(name, value); + } + } + } + } + + private Object determineType(String value) { + if (value == null) { + return value; + } + if (value.startsWith("\"") || value.startsWith("'")) { + return value; + } + try { + return Integer.parseInt(value); + } catch (Exception e) { + return value; + } + } + + public int countByFilter(T entityFrom, T entityTo) { + return countByFilter(entityFrom, entityTo, EMPTY_CRITERIA_MAP, getCountQuery()); + } + + public int countByFilter(T entityFrom, T entityTo, Map criteria) { + return countByFilter(entityFrom, entityTo, criteria, getCountQuery()); + } + + public StringBuilder getCountQuery() { + return new StringBuilder(COUNT_HQL + getCountFromQuery()); + } + + /** + * Restituisce la clausola iniziale per la costruzione di HQL Query. + * + * @return la clausola iniziale per la costruzione di HQL Query. + * @see it.mice.voila.runtime.hibernate.dao.impl.DaoHbmGeneric#getFromQuery() + */ + protected String getCountFromQuery() { + return getFromQuery(); + } + + public int countByFilter(T entityFrom, T entityTo, Map criteria, StringBuilder sql) { + String entityName = getEntityName(entityFrom); + String prefix = " WHERE "; + + prefix = extendTheQueryCriteria(entityFrom, entityTo, criteria, sql, prefix, entityName + ".", ""); + extendTheQueryCriteriaWithAcl(sql, prefix, entityName, "findByFilter"); +// prepareGroupBy(entityFrom, entityTo, criteria, sql); + finalizeCountByFilter(entityFrom, entityTo, criteria, sql); + + Query query = getCurrentSession().createQuery(sql.toString()); + setTheStatementFilterForCriteria(entityFrom, entityTo, criteria, query, 0, ""); + setTheStatementFilterForCriteriaWithAcl(query, entityName, "findByFilter"); + Long totRecords = (Long) query.uniqueResult(); + if (logger.isDebugEnabled()) { + logger.debug("countByFilter: BEAN FROM=" + entityFrom); + logger.debug("countByFilter: BEAN TO=" + entityTo); + logger.debug("countByFilter: SQL=" + sql); + logger.debug("countByFilter: Num of records=" + totRecords); + } + return totRecords.intValue(); + } + + public SessionFactory getSessionFactory() { + return sessionFactory; + } + + public void setSessionFactory(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + public Session getCurrentSession() { + Session retSession = getSessionFactory().getCurrentSession(); + if (isEnableNotDeletedEntityFilter()) { + retSession.enableFilter("notDeletedEntities"); + } + retSession.setFlushMode(FlushMode.parse(getSqlCommandOption().getFlushMode())); + return retSession; + } + + public SqlCommandOption getSqlCommandOption() { + return sqlCommandOption; + } + + public void setSqlCommandOption(SqlCommandOption sqlCommandOption) { + this.sqlCommandOption = sqlCommandOption; + } + + public boolean isEnableNotDeletedEntityFilter() { + return enableNotDeletedEntityFilter; + } + + public void setEnableNotDeletedEntityFilter(boolean enableNotDeletedEntityFilter) { + this.enableNotDeletedEntityFilter = enableNotDeletedEntityFilter; + } + + public java.sql.Timestamp getCurrentTimestamp() + { + return new java.sql.Timestamp(System.currentTimeMillis()); + } + + private void fillParameterEntity(T parameterEntity, T loadedObject) { + evictIfNecessary(loadedObject); + if (loadedObject != parameterEntity) { + if (logger.isInfoEnabled()) { + logger.info("Found a duplicated object with the same identifier in the hibernate session. Try to resolve aniway. Please check results !"); + } + parameterEntity.setInternalEntityStateToLoaded(); + parameterEntity.setObjectDump(loadedObject.getObjectDump()); + parameterEntity.setInternalEntityStateToLoaded(); + } + } + + public T insertInternal(T theEntity) { + if (!theEntity.isNewEntity()) { + if (logger.isDebugEnabled()) { + logger.debug("Operation 'insert' discarded because the entity is not in new internal status: " + theEntity); + } + return theEntity; + } + + getCurrentSession().save(theEntity); + flushIfNecessary(); + if (logger.isDebugEnabled()) { + logger.debug("insert -> success: " + theEntity); + } + evictIfNecessary(theEntity); + return theEntity; + } + + public T updateInternal(T theEntity) { + clearSessionBeforeUpdateIfNecessary(); + try { + getCurrentSession().update(theEntity); + flushIfNecessary(); + } catch (StaleObjectStateException sose) { + throw new BusinessException("message.staleObjectStateException"); + } + if (logger.isDebugEnabled()) { + logger.debug("update -> success: " + theEntity); + } + evictIfNecessary(theEntity); + return theEntity; + } + + public void deleteInternal(T theEntity) { + try { + getCurrentSession().delete(theEntity); + } catch (PropertyValueException e) { + if (logger.isWarnEnabled()) { + logger.warn("Exception trying to delete an entity, try to load it before retry deletion..."); + } + getCurrentSession().evict(theEntity); + T entityToDelete = findByPrimaryKeyNoCache(theEntity); + entityToDelete.setInternalEntityStateToDeleted(); + getCurrentSession().delete(entityToDelete); + } + flushIfNecessary(); + if (logger.isDebugEnabled()) { + logger.debug("delete -> success: " + theEntity); + } + evictIfNecessary(theEntity); + } + + public Collection list(Query query) { + Collection result = query.list(); + if (getSqlCommandOption().isEvictHibernateListElementImmediatly()) { + Iterator resultIt = result.iterator(); + while (resultIt.hasNext()) { + T element = (T) resultIt.next(); + evictListElementIfNecessary(element); + } + } + return result; + } + + public T saveOrUpdate(T theEntity) { + if (theEntity.isChangedEntity()) { + return updateInternal(theEntity); + } + if (theEntity.isNewEntity()) { + return insertInternal(theEntity); + } + if (logger.isDebugEnabled()) { + logger.debug("Operation 'saveOrUpdate' discarded because the entity is not in new or changed internal status: " + theEntity); + } + return theEntity; + } + + private void flushIfNecessary() { + if (getSqlCommandOption().isFlushHibernateSessionImmediatly()) { + getCurrentSession().flush(); + if (logger.isDebugEnabled()) { + logger.debug("Flushing entity immediatly."); + } + } + } + + private void clearSessionBeforeUpdateIfNecessary() { + if (getSqlCommandOption().isClearHibernateSessionBeforeUpdate()) { + getCurrentSession().clear(); + if (logger.isDebugEnabled()) { + logger.debug("Clear hibernate session before update command execution."); + } + } + } + + private void evictIfNecessary(T theEntity) { + if (getSqlCommandOption().isEvictHibernateElementImmediatly()) { + getCurrentSession().evict(theEntity); + if (logger.isDebugEnabled()) { + logger.debug("Evict entity immediatly."); + } + } + } + + /** + * Evict all object list if evictHibernateListElement is set to true in applicationDAO + * @param theEntity + */ + private void evictListElementIfNecessary(T theEntity) { + getCurrentSession().evict(theEntity); + if (logger.isDebugEnabled()) { + logger.debug("Evict list entity element immediatly."); + } + + } + + protected String extendQueryCriteria(StringBuilder sql, String prefix, Object valueFrom, Object valueTo, String parameterName, Object criteriaType) { + return extendQueryCriteria(sql, prefix, valueFrom, valueTo, parameterName, criteriaType, true); + } + + protected String extendQueryCriteria(StringBuilder sql, String prefix, Object valueFrom, Object valueTo, String parameterName, Object criteriaType, boolean useUpper) { + + criteriaType = convertCriteriaToByte(criteriaType); + + if (criteriaType == CriteriaType.DEFAULT && valueFrom instanceof String && valueFrom != null && valueFrom.equals(valueTo)) { + criteriaType = CriteriaType.EQUALS; + } + + if (criteriaType == CriteriaType.DEFAULT) { + if (valueFrom instanceof String) { + return appendToFilterLike(sql, prefix, valueFrom, parameterName, useUpper); + } else { + return appendToFilterFromTo(sql, prefix, valueFrom, valueTo, parameterName); + } + } + + if (criteriaType.equals(CriteriaType.NONE)) { + return prefix; + } + + if (criteriaType.equals(CriteriaType.EQUALS)) { + if (valueFrom != null) { + if (valueFrom instanceof String) { + sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(parameterName, useUpper)).append(" = ?"); + } else { + sql.append(prefix).append(parameterName).append(" = ?"); + } + prefix = " AND "; + } + return prefix; + } + + if (criteriaType.equals(CriteriaType.NOTEQUALS)) { + if (valueFrom != null) { + if (valueFrom instanceof String) { + sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(parameterName, useUpper)).append(" != ?"); + } else { + sql.append(prefix).append(parameterName).append(" != ?"); + } + prefix = " AND "; + } + return prefix; + } + + if (criteriaType.equals(CriteriaType.IS_NULL)) { + sql.append(prefix).append(parameterName).append(" IS NULL "); + prefix = " AND "; + return prefix; + } + + if (criteriaType.equals(CriteriaType.IS_NOT_NULL)) { + sql.append(prefix).append(parameterName).append(" IS NOT NULL "); + prefix = " AND "; + return prefix; + } + + if (criteriaType.equals(CriteriaType.STARTWITH) || criteriaType.equals(CriteriaType.ENDWITH) || criteriaType.equals(CriteriaType.CONTAINS)) + { + return appendToFilterLike(sql, prefix, valueFrom, parameterName, useUpper); + } + + if (criteriaType.equals(CriteriaType.NOT_STARTWITH) || criteriaType.equals(CriteriaType.NOT_ENDWITH) || criteriaType.equals(CriteriaType.NOT_CONTAINS)) + { + return appendToFilterNotLike(sql, prefix, valueFrom, parameterName, useUpper); + } + + if (criteriaType.equals(CriteriaType.GREATER_OR_EQUAL_THAN)) { + return appendToFilterFromTo(sql, prefix, valueFrom, null, parameterName); + } + + if (criteriaType.equals(CriteriaType.LESS_OR_EQUAL_THAN)) { + return appendToFilterFromTo(sql, prefix, null, valueFrom, parameterName); + } + + if (criteriaType.equals(CriteriaType.BETWEEN)) { + return appendToFilterFromTo(sql, prefix, valueFrom, valueTo, parameterName); + } + + if (criteriaType.equals(CriteriaType.NOT_BETWEEN)) { + return appendToFilterNotBetween(sql, prefix, valueFrom, valueTo, parameterName); + } + + if (criteriaType instanceof CriteriaType.InClause) { + Object listValue = ((CriteriaType.InClause)criteriaType).getListValue(); + return appendToFilterIn(sql, prefix, listValue, parameterName); + } + + if (criteriaType instanceof CriteriaType.NotInClause) { + Object listValue = ((CriteriaType.NotInClause)criteriaType).getListValue(); + return appendToFilterNotIn(sql, prefix, listValue, parameterName); + } + + logger.warn("Unrecognized criteria type: " + criteriaType + ". Check your query. Filter discarded !"); + return prefix; + } + + protected int setStatementFilterForCriteria(Query query, int counter, Object valueFrom, Object valueTo, Object criteriaType) { + return setStatementFilterForCriteria(query, counter, valueFrom, valueTo, criteriaType, true); + } + + protected int setStatementFilterForCriteria(Query query, int counter, Object valueFrom, Object valueTo, Object criteriaType, boolean useUpper) { + criteriaType = convertCriteriaToByte(criteriaType); + + if (criteriaType == CriteriaType.DEFAULT && valueFrom instanceof String && valueFrom != null && valueFrom.equals(valueTo)) { + criteriaType = CriteriaType.EQUALS; + } + + if (criteriaType == CriteriaType.DEFAULT) { + if (valueFrom instanceof String) { + return setStatementFilterLike( + query, + counter, + valueFrom, + useUpper + ); + } else { + return setStatementFilterFromTo( + query, + counter, + valueFrom, + valueTo + ); + } + } + + if (criteriaType.equals(CriteriaType.NONE) || criteriaType.equals(CriteriaType.IS_NULL) || criteriaType.equals(CriteriaType.IS_NOT_NULL)) { + return counter; + } + + if (criteriaType.equals(CriteriaType.EQUALS) || criteriaType.equals(CriteriaType.NOTEQUALS)) { + return setStatementFilter(query, counter, valueFrom, useUpper); + } + + if (criteriaType.equals(CriteriaType.STARTWITH) || criteriaType.equals(CriteriaType.NOT_STARTWITH)) { + return setStatementFilterLike(query, counter, valueFrom, "", "%", useUpper); + } + + if (criteriaType.equals(CriteriaType.ENDWITH) || criteriaType.equals(CriteriaType.NOT_ENDWITH)) { + return setStatementFilterLike(query, counter, valueFrom, "%", "", useUpper); + } + + if (criteriaType.equals(CriteriaType.CONTAINS) || criteriaType.equals(CriteriaType.NOT_CONTAINS)) { + return setStatementFilterLike(query, counter, valueFrom, "%", "%", useUpper); + } + + if (criteriaType.equals(CriteriaType.GREATER_OR_EQUAL_THAN)) { + return setStatementFilterFromTo( + query, + counter, + valueFrom, + null + ); + } + + if (criteriaType.equals(CriteriaType.LESS_OR_EQUAL_THAN)) { + return setStatementFilterFromTo( + query, + counter, + null, + valueFrom + ); + } + + if (criteriaType.equals(CriteriaType.BETWEEN) || criteriaType.equals(CriteriaType.NOT_BETWEEN)) { + return setStatementFilterFromTo( + query, + counter, + valueFrom, + valueTo + ); + } + + if (criteriaType instanceof CriteriaType.InClause) { + Object listValue = ((CriteriaType.InClause)criteriaType).getListValue(); + return setStatementFilterIn(query, counter, listValue); + } + + if (criteriaType instanceof CriteriaType.NotInClause) { + Object listValue = ((CriteriaType.NotInClause)criteriaType).getListValue(); + return setStatementFilterIn(query, counter, listValue); + } + + logger.warn("Unrecognized criteria type: " + criteriaType + ". Check your query. Filter discarded !"); + return counter; + } + + protected String appendToFilterLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName) { + return appendToFilterLike(sql, prefix, fieldFrom, columnName, true); + } + + protected String appendToFilterLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName, boolean useUpper) { + if (fieldFrom != null) { + sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(columnName, useUpper)).append(" LIKE ?"); + prefix = " AND "; + } + return prefix; + } + + protected String appendToFilterNotLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName) { + return appendToFilterNotLike(sql, prefix, fieldFrom, columnName, true); + } + + protected String appendToFilterNotLike(StringBuilder sql, String prefix, Object fieldFrom, String columnName, boolean useUpper) { + if (fieldFrom != null) { + sql.append(prefix).append(sqlCommandOption.getStatementFilterColumn(columnName, useUpper)).append(" NOT LIKE ?"); + prefix = " AND "; + } + return prefix; + } + + protected String appendToFilterIn(StringBuilder sql, String prefix, Object array, String columnName) { + return appendToFilterIn(sql, prefix, array, columnName, false); + } + + protected String appendToFilterNotIn(StringBuilder sql, String prefix, Object array, String columnName) { + return appendToFilterIn(sql, prefix, array, columnName, true); + } + + protected String appendToFilterIn(StringBuilder sql, String prefix, Object array, String columnName, boolean useNot) { + if (array != null) { + if (useNot) { + sql.append(prefix).append(columnName).append(" NOT IN ("); + } else { + sql.append(prefix).append(columnName).append(" IN ("); + } + if (array instanceof Object[]) { + Object[] target = (Object[])array; + String delimiter = ""; + for (int i=0; i= ?"); + prefix = " AND "; + } + if (fieldFrom == null && fieldTo != null) { + sql.append(prefix).append(columnName).append(" <= ?"); + prefix = " AND "; + } + return prefix; + } + + protected String appendToFilterNotBetween(StringBuilder sql, String prefix, Object fieldFrom, Object fieldTo, String columnName) { + sql.append(prefix).append(columnName).append(" NOT BETWEEN ? AND ?"); + prefix = " AND "; + return prefix; + } + + /** + * @param query + * @param counter + * @param fieldFrom + */ + protected int setStatementFilterFromTo(Query query, int counter, Object fieldFrom, Object fieldTo) { + if (fieldFrom != null && fieldTo != null) { + setStatementFilter(query, counter++, fieldFrom); + if (!fieldFrom.equals(fieldTo)) { + setStatementFilter(query, counter++, fieldTo); + } + } + if (fieldFrom != null && fieldTo == null) { + setStatementFilter(query, counter++, fieldFrom); + } + if (fieldFrom == null && fieldTo != null) { + setStatementFilter(query, counter++, fieldTo); + } + return counter; + } + + /** + * @param query + * @param counter + * @param fieldFrom + */ + protected int setStatementFilter(Query query, int counter, Object fieldFrom) { + return setStatementFilter(query, counter, fieldFrom, true); + } + protected int setStatementFilter(Query query, int counter, Object fieldFrom, boolean useUpper) { + if (fieldFrom != null) { + if (fieldFrom instanceof String) { + if (getSqlCommandOption().isLikeFilterIgnoreCase() && useUpper) { + if (logger.isDebugEnabled()) { + logger.debug("Setting String parameter number " + counter + " to value <" + ((String) fieldFrom).toUpperCase() + ">"); + } + query.setString(counter++, ((String) fieldFrom).toUpperCase()); + } else { + if (logger.isDebugEnabled()) { + logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setString(counter++, ((String) fieldFrom)); + } + } else if (fieldFrom instanceof java.sql.Timestamp) { + if (logger.isDebugEnabled()) { + logger.debug("Setting Timestamp parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setTimestamp(counter++, (Timestamp) fieldFrom); + } else if (fieldFrom instanceof java.util.Date) { + if (logger.isDebugEnabled()) { + logger.debug("Setting java.util.Date parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setDate(counter++, (Date) fieldFrom); + } else if (fieldFrom instanceof java.sql.Date) { + if (logger.isDebugEnabled()) { + logger.debug("Setting java.sql.Date parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setDate(counter++, (java.sql.Date) fieldFrom); + } else if (fieldFrom instanceof java.lang.Number) { + if (logger.isDebugEnabled()) { + logger.debug("Setting Double parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setDouble(counter++, ((Number) fieldFrom).doubleValue()); + } else if (fieldFrom instanceof java.lang.Boolean) { + if (logger.isDebugEnabled()) { + logger.debug("Setting Boolean parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setBoolean(counter++, ((Boolean) fieldFrom).booleanValue()); + } + } + return counter; + } + + /** + * @param query + * @param counter + * @param fieldFrom + */ + protected int setStatementFilterLike(Query query, int counter, Object fieldFrom) { + return setStatementFilterLike(query, counter, fieldFrom, true); + } + + protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, boolean useUpper) { + if (fieldFrom != null) { + if (fieldFrom instanceof String) { + if (logger.isDebugEnabled()) { + logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setString(counter++, sqlCommandOption.getStatementFilterLike((String) fieldFrom, useUpper)); + } + } + return counter; + } + + protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, String likeFilterMethodLeftSymbolParam, String likeFilterMethodRightSymbolParam) { + return setStatementFilterLike(query, counter, fieldFrom, likeFilterMethodLeftSymbolParam, likeFilterMethodRightSymbolParam, true); + } + + protected int setStatementFilterLike(Query query, int counter, Object fieldFrom, String likeFilterMethodLeftSymbolParam, String likeFilterMethodRightSymbolParam, boolean useUpper) { + if (fieldFrom != null) { + if (logger.isDebugEnabled()) { + logger.debug("Setting String parameter number " + counter + " to value <" + fieldFrom + ">"); + } + query.setString(counter++, sqlCommandOption.getStatementFilterLike(fieldFrom.toString(), likeFilterMethodLeftSymbolParam, likeFilterMethodRightSymbolParam, useUpper)); + } + return counter; + } + + protected int setStatementFilterIn(Query query, int counter, Object array) { + if (array != null) { + if (array instanceof Object[]) { + Object[] target = (Object[])array; + for (int i=0; i"); + } + query.setParameter(counter++, target[i]); + } + } + if (array instanceof Collection) { + Iterator i = ((Collection)array).iterator(); + while (i.hasNext()) { + Object parm = i.next(); + if (logger.isDebugEnabled()) { + logger.debug("Setting IN parameter number " + counter + " to value <" + parm + ">"); + } + query.setParameter(counter++, parm); + } + } + } + return counter; + } + + protected String enhanceOrderByWithPrefix(String orderBy, String prefix, String defaultOrderBy) { + if (orderBy == null || orderBy.trim().length() == 0) { + return defaultOrderBy; + } + + StringBuilder result = new StringBuilder(" ORDER BY "); + String delimiter = ""; + String[] orderKeys = orderBy.split(","); + for (int i=0; iBlob object from a byte array using the + * hibernate specific implementation. The returned object will be initially + * immutable. + * + * @param bytes a byte array + * @return the Blob object + */ + public Blob createBlob(byte[] bytes) { + return Hibernate.createBlob(bytes); + } + + /** + * Utility method to create a Blob object from an InputStram using the + * hibernate specific implementation. The returned object will be initially + * immutable. + * + * @param stream a binary stream + * @return the Blob object + * @throws IOException + */ + public Blob createBlob(InputStream stream) throws IOException { + return Hibernate.createBlob(stream); + } + + /** + * Utility method to create a Blob object from an InputStram using the + * hibernate specific implementation. The returned object will be initially + * immutable. + * + * @param stream a binary stream + * @param length the number of bytes in the stream + * @return the Blob object + */ + public Blob createBlob(InputStream stream, int length) { + return Hibernate.createBlob(stream, length); + } + + public Object getCriteriaObject(Map criteria, String name) { + return criteria.get(name); + } + + public boolean hasCriteria(Map criteria, String name) { + return !StringUtils.isEmpty(getCriteriaAsString(criteria, name)); + } + + public String getCriteriaAsString(Map criteria, String name) { + Object result = getCriteriaObject(criteria, name); + if (result != null) { + return result.toString(); + } + return null; + } + + protected Collection findByParent(String fromQuery, String entityName, String parentEntityName, Entity parentEntity, String operationName) { + StringBuilder sql = new StringBuilder(fromQuery); + sql.append(" WHERE ").append(entityName).append(".").append(parentEntityName).append(" = :").append(parentEntityName); + extendTheQueryCriteriaWithAcl(sql, " AND ", entityName, operationName); + sql.append(getOrderBy()); + Query query = getCurrentSession().createQuery(sql.toString()); + query.setParameter(parentEntityName, parentEntity); + setTheStatementFilterForCriteriaWithAcl(query, entityName, operationName); + return list(query); + } +} diff --git a/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/interceptor/CustomInterceptor.java b/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/interceptor/CustomInterceptor.java index 385277ce43baf68347bbaefb809770e7b4d2acb6..5311ffd113f7874b463a7444c8c05de3af88aa97 100644 --- a/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/interceptor/CustomInterceptor.java +++ b/voila-runtime-hibernate/src/main/java/it/mice/voila/runtime/hibernate/interceptor/CustomInterceptor.java @@ -1,77 +1,146 @@ -package it.mice.voila.runtime.hibernate.interceptor; - -import it.mice.voila.runtime.entity.Entity; - -import java.util.Iterator; - -import org.hibernate.EmptyInterceptor; -import org.hibernate.SessionFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; - - -/** - * Created by IntelliJ IDEA. - * User: zzy9v4 - * Date: 23-feb-2007 - * Time: 10.39.27 - * To change this template use File | Settings | File Templates. - */ -public class CustomInterceptor extends EmptyInterceptor implements BeanFactoryAware { - /** - * - */ - private static final long serialVersionUID = -8731771375437963623L; - private BeanFactory beanFactory; - private SessionFactory sessionFactory; - - public SessionFactory getSessionFactory() { - if (sessionFactory == null) { - sessionFactory = beanFactory.getBean(SessionFactory.class); - } - return sessionFactory; - } - - /** - * Called to distinguish between transient and detached entities. The return value determines the - * state of the entity with respect to the current session. - *

    - *
  • Boolean.TRUE - the entity is transient - *
  • Boolean.FALSE - the entity is detached - *
  • null - Hibernate uses the unsaved-value mapping and other heuristics to - * determine if the object is unsaved - *
- * - * @param entity a transient or detached entity - * @return Boolean or null to choose default behaviour - */ - public Boolean isTransient(Object entity) { - if (entity instanceof Entity) { - Entity jfEntity = (Entity) entity; - if (jfEntity.isNewEntity()) { - return null; - } else { - return Boolean.FALSE; - } - } - return super.isTransient(entity); - } - - public void postFlush(Iterator iterator) { - while (iterator.hasNext()) { - Object element = (Object) iterator.next(); - if (element instanceof Entity) { - Entity jfEntity = (Entity) element; - if (jfEntity.isChangedEntity() || jfEntity.isNewEntity()) { - jfEntity.setInternalEntityStateToLoaded(); - } - } - } - super.postFlush(iterator); - } - - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } -} +package it.mice.voila.runtime.hibernate.interceptor; + +import it.mice.voila.runtime.entity.Entity; + +import java.io.Serializable; +import java.util.Iterator; + +import org.hibernate.EmptyInterceptor; +import org.hibernate.SessionFactory; +import org.hibernate.cache.CacheKey; +import org.hibernate.impl.SessionImpl; +import org.hibernate.persister.entity.AbstractEntityPersister; +import org.hibernate.persister.entity.EntityPersister; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; + + +/** + * Created by IntelliJ IDEA. + * User: zzy9v4 + * Date: 23-feb-2007 + * Time: 10.39.27 + * To change this template use File | Settings | File Templates. + */ +public class CustomInterceptor extends EmptyInterceptor implements BeanFactoryAware { + /** + * + */ + private static final long serialVersionUID = -8731771375437963623L; + private BeanFactory beanFactory; + private SessionFactory sessionFactory; + + public SessionFactory getSessionFactory() { + if (sessionFactory == null) { + sessionFactory = beanFactory.getBean(SessionFactory.class); + } + return sessionFactory; + } + + /** + * Called to distinguish between transient and detached entities. The return value determines the + * state of the entity with respect to the current session. + *
    + *
  • Boolean.TRUE - the entity is transient + *
  • Boolean.FALSE - the entity is detached + *
  • null - Hibernate uses the unsaved-value mapping and other heuristics to + * determine if the object is unsaved + *
+ * + * @param entity a transient or detached entity + * @return Boolean or null to choose default behaviour + */ + public Boolean isTransient(Object entity) { + if (entity instanceof Entity) { + Entity jfEntity = (Entity) entity; + if (jfEntity.isNewEntity()) { + if (getSessionFactory() != null) { + SessionImpl simpl = (SessionImpl) getSessionFactory().getCurrentSession(); + AbstractEntityPersister ep = (AbstractEntityPersister)simpl.getEntityPersister(entity.getClass().getName(), entity); +// if (ep.isVersioned()) { +// final Object version = ep.getVersion( entity, simpl.getEntityMode() ); +// if (version != null) { +// return Boolean.FALSE; +// } else { +// Object id = simpl.getEntityPersister( entity.getClass().getName(), entity ).getIdentifier( entity, simpl.getEntityMode() ); +// return id == null; +// } +// } + return isTransient(entity, ep, simpl); + } + return null; + } else { + return Boolean.FALSE; + } + } + return super.isTransient(entity); + } + + public Boolean isTransient(Object entity, AbstractEntityPersister entityPersister, SessionImpl session) { + final Serializable id; + if ( entityPersister.canExtractIdOutOfEntity() ) { + id = entityPersister.getIdentifier( entity, session.getEntityMode() ); + } + else { + id = null; + } + // we *always* assume an instance with a null + // identifier or no identifier property is unsaved! + if ( id == null ) { + return Boolean.TRUE; + } + + // check the version unsaved-value, if appropriate +// final Object version = entityPersister.getVersion( entity, session.getEntityMode() ); +// if ( entityPersister.isVersioned() ) { +// // let this take precedence if defined, since it works for +// // assigned identifiers +// Boolean result = entityPersister.getEntityMetamodel().getVersionProperty() +// .getUnsavedValue().isUnsaved( version ); +// if ( result != null ) { +// return result; +// } +// } + + // check the id unsaved-value + Boolean result = entityPersister.getEntityMetamodel().getIdentifierProperty() + .getUnsavedValue().isUnsaved( id ); + if ( result != null ) { + return result; + } + + // check to see if it is in the second-level cache + if ( entityPersister.hasCache() ) { + CacheKey ck = new CacheKey( + id, + entityPersister.getIdentifierType(), + entityPersister.getRootEntityName(), + session.getEntityMode(), + session.getFactory() + ); + if ( entityPersister.getCache().get( ck, session.getTimestamp() ) != null ) { + return Boolean.FALSE; + } + } + + return null; + } + + public void postFlush(Iterator iterator) { + while (iterator.hasNext()) { + Object element = (Object) iterator.next(); + if (element instanceof Entity) { + Entity jfEntity = (Entity) element; + if (jfEntity.isChangedEntity() || jfEntity.isNewEntity()) { + jfEntity.setInternalEntityStateToLoaded(); + } + } + } + super.postFlush(iterator); + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } +}