import java.lang.reflect.Field;\r
import java.util.ArrayList;\r
import java.util.Collection;\r
+import java.util.EnumSet;\r
import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.Iterator;\r
import java.util.UUID;\r
\r
import org.apache.log4j.Logger;\r
-import org.apache.lucene.search.Sort;\r
-import org.apache.lucene.search.SortField;\r
import org.hibernate.Criteria;\r
import org.hibernate.FlushMode;\r
import org.hibernate.HibernateException;\r
import org.hibernate.Session;\r
import org.hibernate.criterion.Criterion;\r
import org.hibernate.criterion.DetachedCriteria;\r
+import org.hibernate.criterion.Disjunction;\r
import org.hibernate.criterion.Example;\r
import org.hibernate.criterion.Example.PropertySelector;\r
+import org.hibernate.criterion.LogicalExpression;\r
import org.hibernate.criterion.Order;\r
import org.hibernate.criterion.ProjectionList;\r
import org.hibernate.criterion.Projections;\r
import org.hibernate.criterion.Restrictions;\r
+import org.hibernate.criterion.Subqueries;\r
+import org.hibernate.envers.AuditReader;\r
+import org.hibernate.envers.AuditReaderFactory;\r
import org.hibernate.envers.query.AuditQuery;\r
import org.hibernate.metadata.ClassMetadata;\r
-import org.hibernate.search.FullTextQuery;\r
+import org.hibernate.sql.JoinType;\r
import org.hibernate.type.Type;\r
import org.joda.time.DateTime;\r
import org.springframework.beans.factory.annotation.Autowired;\r
import org.springframework.util.ReflectionUtils;\r
\r
import eu.etaxonomy.cdm.model.common.CdmBase;\r
-import eu.etaxonomy.cdm.model.common.User;\r
+import eu.etaxonomy.cdm.model.common.IPublishable;\r
import eu.etaxonomy.cdm.model.common.VersionableEntity;\r
+import eu.etaxonomy.cdm.model.permission.User;\r
+import eu.etaxonomy.cdm.model.view.AuditEvent;\r
import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;\r
+import eu.etaxonomy.cdm.persistence.dao.common.Restriction;\r
+import eu.etaxonomy.cdm.persistence.dao.common.Restriction.Operator;\r
import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;\r
import eu.etaxonomy.cdm.persistence.dto.MergeResult;\r
import eu.etaxonomy.cdm.persistence.hibernate.PostMergeEntityListener;\r
import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
\r
-\r
/**\r
- * @author a.mueller\r
- * FIXME CdmEntityDaoBase is abstract, can it be annotated with @Repository?\r
+ * @author a.mueller FIXME CdmEntityDaoBase is abstract, can it be annotated\r
+ * with @Repository?\r
*/\r
@Repository\r
-public abstract class CdmEntityDaoBase<T extends CdmBase> extends DaoBase implements ICdmEntityDao<T> {\r
+public abstract class CdmEntityDaoBase<T extends CdmBase>\r
+ extends DaoBase\r
+ implements ICdmEntityDao<T> {\r
+\r
private static final Logger logger = Logger.getLogger(CdmEntityDaoBase.class);\r
\r
- protected int flushAfterNo = 1000; //large numbers may cause synchronisation errors when commiting the session !!\r
+ protected int flushAfterNo = 1000; // large numbers may cause\r
+ // synchronisation errors when commiting\r
+ // the session !!\r
\r
protected Class<T> type;\r
\r
-// protected Version version = Configuration.luceneVersion;\r
-\r
@Autowired\r
-// @Qualifier("defaultBeanInitializer")\r
+ // @Qualifier("defaultBeanInitializer")\r
protected IBeanInitializer defaultBeanInitializer;\r
\r
public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer) {\r
@Autowired\r
private ReferringObjectMetadataFactory referringObjectMetadataFactory;\r
\r
+ protected static final EnumSet<Operator> LEFTOUTER_OPS = EnumSet.of(Operator.AND_NOT, Operator.OR, Operator.OR_NOT);\r
\r
- public CdmEntityDaoBase(Class<T> type){\r
+ public CdmEntityDaoBase(Class<T> type) {\r
this.type = type;\r
+ assert type != null;\r
logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");\r
}\r
\r
defaultBeanInitializer.initialize(t, propertyPaths);\r
}\r
\r
- //TODO this method should be moved to a concrete class (not typed)\r
- public UUID saveCdmObj(CdmBase cdmObj) throws DataAccessException {\r
+ // TODO this method should be moved to a concrete class (not typed)\r
+ public UUID saveCdmObj(CdmBase cdmObj) throws DataAccessException {\r
getSession().saveOrUpdate(cdmObj);\r
return cdmObj.getUuid();\r
}\r
\r
- //TODO: Replace saveCdmObj() by saveCdmObject_\r
- private UUID saveCdmObject_(T cdmObj){\r
+ // TODO: Replace saveCdmObj() by saveCdmObject_\r
+ private UUID saveCdmObject_(T cdmObj) {\r
getSession().saveOrUpdate(cdmObj);\r
return cdmObj.getUuid();\r
}\r
\r
- //TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of ServiceBase.saveCdmObjectAll()?\r
- //TODO: why does this use saveCdmObject_ which actually savesOrUpdateds data ?\r
+ // TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of\r
+ // ServiceBase.saveCdmObjectAll()?\r
+ // TODO: why does this use saveCdmObject_ which actually savesOrUpdateds\r
+ // data ?\r
@Override\r
- public Map<UUID, T> saveAll(Collection<T> cdmObjCollection){\r
+ public Map<UUID, T> saveAll(Collection<? extends T> cdmObjCollection) {\r
int types = cdmObjCollection.getClass().getTypeParameters().length;\r
- if (types > 0){\r
- if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}\r
+ if (types > 0) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);\r
+ }\r
}\r
\r
- Map<UUID, T> resultMap = new HashMap<UUID, T>();\r
- Iterator<T> iterator = cdmObjCollection.iterator();\r
+ Map<UUID, T> resultMap = new HashMap<>();\r
+ Iterator<? extends T> iterator = cdmObjCollection.iterator();\r
int i = 0;\r
- while(iterator.hasNext()){\r
- if ( ( (i % 2000) == 0) && (i > 0) ){logger.debug("Saved " + i + " objects" );}\r
+ while (iterator.hasNext()) {\r
+ if (((i % 2000) == 0) && (i > 0)) {\r
+ logger.debug("Saved " + i + " objects");\r
+ }\r
T cdmObj = iterator.next();\r
UUID uuid = saveCdmObject_(cdmObj);\r
- if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Save cdmObj: " + (cdmObj == null ? null : cdmObj.toString()));\r
+ }\r
resultMap.put(uuid, cdmObj);\r
i++;\r
- if ( (i % flushAfterNo) == 0){\r
- try{\r
- if (logger.isDebugEnabled()){logger.debug("flush");}\r
+ if ((i % flushAfterNo) == 0) {\r
+ try {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("flush");\r
+ }\r
flush();\r
- }catch(Exception e){\r
+ } catch (Exception e) {\r
logger.error("An exception occurred when trying to flush data");\r
e.printStackTrace();\r
throw new RuntimeException(e);\r
}\r
}\r
\r
- if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
+ if (logger.isInfoEnabled()) {\r
+ logger.info("Saved " + i + " objects");\r
+ }\r
return resultMap;\r
}\r
\r
- private UUID saveOrUpdateCdmObject(T cdmObj){\r
+ private UUID saveOrUpdateCdmObject(T cdmObj) {\r
getSession().saveOrUpdate(cdmObj);\r
return cdmObj.getUuid();\r
}\r
\r
@Override\r
- public Map<UUID, T> saveOrUpdateAll(Collection<T> cdmObjCollection){\r
+ public Map<UUID, T> saveOrUpdateAll(Collection<T> cdmObjCollection) {\r
int types = cdmObjCollection.getClass().getTypeParameters().length;\r
- if (types > 0){\r
- if (logger.isDebugEnabled()){logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);}\r
+ if (types > 0) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("ClassType: + " + cdmObjCollection.getClass().getTypeParameters()[0]);\r
+ }\r
}\r
\r
- Map<UUID, T> resultMap = new HashMap<UUID, T>();\r
+ Map<UUID, T> resultMap = new HashMap<>();\r
Iterator<T> iterator = cdmObjCollection.iterator();\r
int i = 0;\r
- while(iterator.hasNext()){\r
- if ( ( (i % 2000) == 0) && (i > 0) ){logger.debug("Saved " + i + " objects" );}\r
+ while (iterator.hasNext()) {\r
+ if (((i % 2000) == 0) && (i > 0)) {\r
+ logger.debug("Saved " + i + " objects");\r
+ }\r
T cdmObj = iterator.next();\r
UUID uuid = saveOrUpdateCdmObject(cdmObj);\r
- if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("Save cdmObj: " + (cdmObj == null ? null : cdmObj.toString()));\r
+ }\r
resultMap.put(uuid, cdmObj);\r
i++;\r
- if ( (i % flushAfterNo) == 0){\r
- try{\r
- if (logger.isDebugEnabled()){logger.debug("flush");}\r
+ if ((i % flushAfterNo) == 0) {\r
+ try {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("flush");\r
+ }\r
flush();\r
- }catch(Exception e){\r
+ } catch (Exception e) {\r
logger.error("An exception occurred when trying to flush data");\r
e.printStackTrace();\r
throw new RuntimeException(e);\r
}\r
}\r
\r
- if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
+ if (logger.isInfoEnabled()) {\r
+ logger.info("Saved " + i + " objects");\r
+ }\r
return resultMap;\r
}\r
\r
-\r
-\r
-\r
@Override\r
public T replace(T x, T y) {\r
- if(x.equals(y)) {\r
+ if (x.equals(y)) {\r
return y;\r
}\r
\r
Class<?> commonClass = x.getClass();\r
- if(y != null) {\r
- while(!commonClass.isAssignableFrom(y.getClass())) {\r
- if(commonClass.equals(type)) {\r
+ if (y != null) {\r
+ while (!commonClass.isAssignableFrom(y.getClass())) {\r
+ if (commonClass.equals(type)) {\r
throw new RuntimeException();\r
}\r
commonClass = commonClass.getSuperclass();\r
\r
Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());\r
\r
- for(ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {\r
+ for (ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {\r
\r
- List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x, getSession());\r
+ List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x, getSession());\r
\r
- for(CdmBase referringObject : referringObjects) {\r
- try {\r
- referringObjectMetadata.replace(referringObject,x,y);\r
- getSession().update(referringObject);\r
+ for (CdmBase referringObject : referringObjects) {\r
+ try {\r
+ referringObjectMetadata.replace(referringObject, x, y);\r
+ getSession().update(referringObject);\r
\r
- } catch (IllegalArgumentException e) {\r
- throw new RuntimeException(e.getMessage(),e);\r
- } catch (IllegalAccessException e) {\r
- throw new RuntimeException(e.getMessage(),e);\r
+ } catch (IllegalArgumentException e) {\r
+ throw new RuntimeException(e.getMessage(), e);\r
+ } catch (IllegalAccessException e) {\r
+ throw new RuntimeException(e.getMessage(), e);\r
+ }\r
}\r
- }\r
}\r
return y;\r
}\r
public void clear() throws DataAccessException {\r
Session session = getSession();\r
session.clear();\r
- if (logger.isDebugEnabled()){logger.debug("dao clear end");}\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("dao clear end");\r
+ }\r
}\r
\r
@Override\r
MergeResult<T> result = null;\r
try {\r
@SuppressWarnings("unchecked")\r
- T persistentObject = (T)session.merge(transientObject);\r
- if (logger.isDebugEnabled()){logger.debug("dao merge end");}\r
+ T persistentObject = (T) session.merge(transientObject);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("dao merge end");\r
+ }\r
\r
- if(returnTransientEntity) {\r
- if(transientObject != null && persistentObject != null) {\r
+ if (returnTransientEntity) {\r
+ if (transientObject != null && persistentObject != null) {\r
transientObject.setId(persistentObject.getId());\r
}\r
result = new MergeResult(transientObject, PostMergeEntityListener.getNewEntities(session));\r
public T merge(T transientObject) throws DataAccessException {\r
Session session = getSession();\r
@SuppressWarnings("unchecked")\r
- T persistentObject = (T)session.merge(transientObject);\r
- if (logger.isDebugEnabled()){logger.debug("dao merge end");}\r
+ T persistentObject = (T) session.merge(transientObject);\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("dao merge end");\r
+ }\r
return persistentObject;\r
}\r
\r
@Override\r
- public UUID saveOrUpdate(T transientObject) throws DataAccessException {\r
- if (transientObject == null){\r
- logger.warn("Object to save should not be null. NOP");\r
- return null;\r
+ public UUID saveOrUpdate(T transientObject) throws DataAccessException {\r
+ if (transientObject == null) {\r
+ logger.warn("Object to save should not be null. NOP");\r
+ return null;\r
}\r
- try {\r
- if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate start...");}\r
- if (logger.isDebugEnabled()){logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:" + transientObject.getId() + ", UUID: " + transientObject.getUuid()) ;}\r
+ try {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("dao saveOrUpdate start...");\r
+ }\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("transientObject(" + transientObject.getClass().getSimpleName() + ") ID:"\r
+ + transientObject.getId() + ", UUID: " + transientObject.getUuid());\r
+ }\r
Session session = getSession();\r
- if(transientObject.getId() != 0 && VersionableEntity.class.isAssignableFrom(transientObject.getClass())) {\r
- VersionableEntity versionableEntity = (VersionableEntity)transientObject;\r
+ if (transientObject.getId() != 0 && VersionableEntity.class.isAssignableFrom(transientObject.getClass())) {\r
+ VersionableEntity versionableEntity = (VersionableEntity) transientObject;\r
versionableEntity.setUpdated(new DateTime());\r
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\r
- if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {\r
- User user = (User)authentication.getPrincipal();\r
- versionableEntity.setUpdatedBy(user);\r
+ if (authentication != null && authentication.getPrincipal() != null\r
+ && authentication.getPrincipal() instanceof User) {\r
+ User user = (User) authentication.getPrincipal();\r
+ versionableEntity.setUpdatedBy(user);\r
}\r
}\r
session.saveOrUpdate(transientObject);\r
- if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("dao saveOrUpdate end");\r
+ }\r
return transientObject.getUuid();\r
} catch (NonUniqueObjectException e) {\r
- logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj)");\r
- logger.error(e.getIdentifier());\r
- logger.error(e.getEntityName());\r
+ logger.error("Error in CdmEntityDaoBase.saveOrUpdate(obj). ID=" + e.getIdentifier() + ". Class="\r
+ + e.getEntityName());\r
logger.error(e.getMessage());\r
\r
e.printStackTrace();\r
}\r
\r
@Override\r
- public T save(T newInstance) throws DataAccessException {\r
- if (newInstance == null){\r
- logger.warn("Object to save should not be null. NOP");\r
- return null;\r
+ public <S extends T> S save(S newInstance) throws DataAccessException {\r
+ if (newInstance == null) {\r
+ logger.warn("Object to save should not be null. NOP");\r
+ return null;\r
}\r
- getSession().save(newInstance);\r
+ getSession().save(newInstance);\r
return newInstance;\r
}\r
\r
@Override\r
public UUID update(T transientObject) throws DataAccessException {\r
- if (transientObject == null){\r
- logger.warn("Object to update should not be null. NOP");\r
- return null;\r
+ if (transientObject == null) {\r
+ logger.warn("Object to update should not be null. NOP");\r
+ return null;\r
}\r
- getSession().update(transientObject);\r
+ getSession().update(transientObject);\r
return transientObject.getUuid();\r
}\r
\r
\r
@Override\r
public UUID delete(T persistentObject) throws DataAccessException {\r
- if (persistentObject == null){\r
+ if (persistentObject == null) {\r
logger.warn(type.getName() + " was 'null'");\r
return null;\r
}\r
// I think this is preferable to catching lazy initialization errors\r
// as that solution only swallows and hides the exception, but doesn't\r
// actually solve it.\r
- persistentObject = (T) getSession().merge(persistentObject);\r
+ persistentObject = (T) getSession().merge(persistentObject);\r
getSession().delete(persistentObject);\r
return persistentObject.getUuid();\r
}\r
\r
- @Override\r
+ @Override\r
public T findById(int id) throws DataAccessException {\r
return getSession().get(type, id);\r
}\r
\r
-\r
@Override\r
- public T findByUuid(UUID uuid) throws DataAccessException{\r
+ public T findByUuid(UUID uuid) throws DataAccessException {\r
+ return this.findByUuid(uuid, INCLUDE_UNPUBLISHED);\r
+ }\r
+\r
+ protected T findByUuid(UUID uuid, boolean includeUnpublished) throws DataAccessException {\r
Session session = getSession();\r
Criteria crit = session.createCriteria(type);\r
crit.add(Restrictions.eq("uuid", uuid));\r
crit.addOrder(Order.desc("created"));\r
+ if (IPublishable.class.isAssignableFrom(type) && !includeUnpublished) {\r
+ crit.add(Restrictions.eq("publish", Boolean.TRUE));\r
+ }\r
+\r
@SuppressWarnings("unchecked")\r
- List<T> results = crit.list();\r
+ List<T> results = crit.list();\r
Set<T> resultSet = new HashSet<>();\r
resultSet.addAll(results);\r
- if (resultSet.isEmpty()){\r
+ if (resultSet.isEmpty()) {\r
return null;\r
- }else{\r
- if(resultSet.size() > 1){\r
+ } else {\r
+ if (resultSet.size() > 1) {\r
logger.error("findByUuid() delivers more than one result for UUID: " + uuid);\r
}\r
return results.get(0);\r
}\r
\r
@Override\r
- public T findByUuidWithoutFlush(UUID uuid) throws DataAccessException{\r
- Session session = getSession();\r
- FlushMode currentFlushMode = session.getFlushMode();\r
- try {\r
- // set flush mode to manual so that the session does not flush\r
- // when before performing the query\r
- session.setFlushMode(FlushMode.MANUAL);\r
- Criteria crit = session.createCriteria(type);\r
- crit.add(Restrictions.eq("uuid", uuid));\r
- crit.addOrder(Order.desc("created"));\r
- @SuppressWarnings("unchecked")\r
- List<T> results = crit.list();\r
- if (results.isEmpty()){\r
- return null;\r
- }else{\r
- if(results.size() > 1){\r
- logger.error("findByUuid() delivers more than one result for UUID: " + uuid);\r
- }\r
- return results.get(0);\r
- }\r
- } finally {\r
- // set back the session flush mode\r
- if(currentFlushMode != null) {\r
- session.setFlushMode(currentFlushMode);\r
- }\r
- }\r
+ public T findByUuidWithoutFlush(UUID uuid) throws DataAccessException {\r
+ Session session = getSession();\r
+ FlushMode currentFlushMode = session.getFlushMode();\r
+ try {\r
+ // set flush mode to manual so that the session does not flush\r
+ // when before performing the query\r
+ session.setFlushMode(FlushMode.MANUAL);\r
+ Criteria crit = session.createCriteria(type);\r
+ crit.add(Restrictions.eq("uuid", uuid));\r
+ crit.addOrder(Order.desc("created"));\r
+ @SuppressWarnings("unchecked")\r
+ List<T> results = crit.list();\r
+ if (results.isEmpty()) {\r
+ return null;\r
+ } else {\r
+ if (results.size() > 1) {\r
+ logger.error("findByUuid() delivers more than one result for UUID: " + uuid);\r
+ }\r
+ return results.get(0);\r
+ }\r
+ } finally {\r
+ // set back the session flush mode\r
+ if (currentFlushMode != null) {\r
+ session.setFlushMode(currentFlushMode);\r
+ }\r
+ }\r
}\r
\r
@Override\r
- public List<T> loadList(Collection<Integer> ids, List<String> propertyPaths) throws DataAccessException {\r
+ public List<T> loadList(Collection<Integer> ids, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {\r
\r
if (ids.isEmpty()) {\r
- return new ArrayList<T>(0);\r
+ return new ArrayList<>(0);\r
}\r
\r
- Criteria criteria = prepareList(ids, null, null, null, "id");\r
+ Criteria criteria = prepareList(null, ids, null, null, orderHints, "id");\r
+\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug(criteria.toString());\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ List<T> result = criteria.list();\r
+ defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public List<T> list(Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,\r
+ List<String> propertyPaths) throws DataAccessException {\r
+\r
+ if (uuids == null || uuids.isEmpty()) {\r
+ return new ArrayList<>();\r
+ }\r
+\r
+ Criteria criteria = prepareList(null, uuids, pageSize, pageNumber, orderHints, "uuid");\r
+ @SuppressWarnings("unchecked")\r
+ List<T> result = criteria.list();\r
+ defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+ return result;\r
+ }\r
\r
- if (logger.isDebugEnabled()){logger.debug(criteria.toString());}\r
+ @Override\r
+ public <S extends T> List<S> list(Class<S> clazz, Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,\r
+ List<String> propertyPaths) throws DataAccessException {\r
\r
- @SuppressWarnings("unchecked")\r
- List<T> result = criteria.list();\r
- defaultBeanInitializer.initializeAll(result, propertyPaths);\r
- return result;\r
- }\r
+ if (uuids == null || uuids.isEmpty()) {\r
+ return new ArrayList<>();\r
+ }\r
\r
+ Criteria criteria = prepareList(clazz, uuids, pageSize, pageNumber, orderHints, "uuid");\r
+ @SuppressWarnings("unchecked")\r
+ List<S> result = criteria.list();\r
+ defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+ return result;\r
+ }\r
\r
@Override\r
- public List<T> list(Collection<UUID> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {\r
+ public <S extends T> List<S> list(Class<S> type, List<Restriction<?>> restrictions, Integer limit, Integer start,\r
+ List<OrderHint> orderHints, List<String> propertyPaths) {\r
\r
- Criteria criteria = prepareList(uuids, pageSize, pageNumber, orderHints, "uuid");\r
+ Criteria criteria = createCriteria(type, restrictions, false);\r
+\r
+ addLimitAndStart(criteria, limit, start);\r
+ addOrder(criteria, orderHints);\r
\r
@SuppressWarnings("unchecked")\r
- List<T> result = criteria.list();\r
+ List<S> result = criteria.list();\r
defaultBeanInitializer.initializeAll(result, propertyPaths);\r
return result;\r
}\r
\r
+ /**\r
+ * @param restrictions\r
+ * @param criteria\r
+ */\r
+ private void addRestrictions(List<Restriction<?>> restrictions, DetachedCriteria criteria) {\r
+\r
+ if(restrictions == null || restrictions.isEmpty()){\r
+ return ;\r
+ }\r
+\r
+ List<CriterionWithOperator> perProperty = new ArrayList<>(restrictions.size());\r
+ Map<String, String> aliases = new HashMap<>();\r
+\r
+\r
+\r
+ for(Restriction<?> restriction : restrictions){\r
+ Collection<? extends Object> values = restriction.getValues();\r
+ JoinType jointype = LEFTOUTER_OPS.contains(restriction.getOperator()) ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;\r
+ if(values != null && !values.isEmpty()){\r
+ // ---\r
+ String propertyPath = restriction.getPropertyName();\r
+ String[] props = propertyPath.split("\\.");\r
+ String propertyName;\r
+ if(props.length == 1){\r
+ // direct property of the base type of the criteria\r
+ propertyName = propertyPath;\r
+ } else {\r
+ // create aliases if the propertyName is a dot separated property path\r
+ String aĺiasKey = jointype.name() + "_";\r
+ String aliasedProperty = null;\r
+ String alias = "";\r
+ for(int p = 0; p < props.length -1; p++){\r
+ aĺiasKey = aĺiasKey + (aĺiasKey.isEmpty() ? "" : ".") + props[p];\r
+ aliasedProperty = alias + (alias.isEmpty() ? "" : ".") + props[p];\r
+ if(!aliases.containsKey(aliasedProperty)){\r
+ alias = alias + (alias.isEmpty() ? "" : "_" ) + props[p];\r
+ aliases.put(aĺiasKey, alias);\r
+ criteria.createAlias(aliasedProperty, alias, jointype);\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug("addRestrictions() alias created with aliasKey " + aĺiasKey + " => " + aliasedProperty + " as " + alias);\r
+ }\r
+ }\r
+ }\r
+ propertyName = alias + "." + props[props.length -1];\r
+ }\r
+ // ---\r
+ Criterion[] predicates = new Criterion[values.size()];\r
+ int i = 0;\r
+ for(Object v : values){\r
+ Criterion criterion = createRestriction(propertyName, v, restriction.getMatchMode());\r
+ if(restriction.isNot()){\r
+ if(props.length > 1){\r
+ criterion = Restrictions.or(Restrictions.not(criterion), Restrictions.isNull(propertyName));\r
+ } else {\r
+ criterion = Restrictions.not(criterion);\r
+ }\r
+ }\r
+ predicates[i++] = criterion;\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug("addRestrictions() predicate with " + propertyName + " " + (restriction.getMatchMode() == null ? "=" : restriction.getMatchMode().name()) + " " + v.toString());\r
+ }\r
+ }\r
+ if(restriction.getOperator() == Operator.AND_NOT){\r
+ perProperty.add(new CriterionWithOperator(restriction.getOperator(), Restrictions.and(predicates)));\r
+ } else {\r
+ perProperty.add(new CriterionWithOperator(restriction.getOperator(), Restrictions.or(predicates)));\r
+ }\r
+ } // check has values\r
+ } // loop over restrictions\r
+\r
+ Restriction.Operator firstOperator = null;\r
+ if(!perProperty.isEmpty()){\r
+ LogicalExpression logicalExpression = null;\r
+ for(CriterionWithOperator cwo : perProperty){\r
+ if(logicalExpression == null){\r
+ firstOperator = cwo.operator;\r
+ logicalExpression = Restrictions.and(Restrictions.sqlRestriction("1=1"), cwo.criterion);\r
+ } else {\r
+ switch(cwo.operator){\r
+ case AND:\r
+ case AND_NOT:\r
+ logicalExpression = Restrictions.and(logicalExpression, cwo.criterion);\r
+ break;\r
+ case OR:\r
+ case OR_NOT:\r
+ logicalExpression = Restrictions.or(logicalExpression, cwo.criterion);\r
+ break;\r
+ default:\r
+ throw new RuntimeException("Unsupported Operator");\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+\r
+ criteria.add(logicalExpression);\r
+// if(firstOperator == Operator.OR){\r
+// // OR\r
+// } else {\r
+// // AND\r
+// criteria.add(Restrictions.and(queryStringCriterion, logicalExpression));\r
+// }\r
+ }\r
+ if(logger.isDebugEnabled()){\r
+ logger.debug("addRestrictions() final criteria: " + criteria.toString());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @param propertyName\r
+ * @param value\r
+ * @param matchMode\r
+ * is only applied if the <code>value</code> is a\r
+ * <code>String</code> object\r
+ * @param criteria\r
+ * @return\r
+ */\r
+ private Criterion createRestriction(String propertyName, Object value, MatchMode matchMode) {\r
+\r
+ Criterion restriction;\r
+ if (value == null) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createRestriction() " + propertyName + " is null ");\r
+ }\r
+ restriction = Restrictions.isNull(propertyName);\r
+ } else if (matchMode == null || !(value instanceof String)) {\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createRestriction() " + propertyName + " = " + value.toString());\r
+ }\r
+ restriction = Restrictions.eq(propertyName, value);\r
+ } else {\r
+ String queryString = (String) value;\r
+ if (logger.isDebugEnabled()) {\r
+ logger.debug("createRestriction() " + propertyName + " " + matchMode.getMatchOperator() + " "\r
+ + matchMode.queryStringFrom(queryString));\r
+ }\r
+ switch(matchMode){\r
+ case BEGINNING:\r
+ restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.START);\r
+ break;\r
+ case END:\r
+ restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.END);\r
+ break;\r
+ case LIKE:\r
+ restriction = Restrictions.ilike(propertyName, matchMode.queryStringFrom(queryString), org.hibernate.criterion.MatchMode.ANYWHERE);\r
+ break;\r
+ case EXACT:\r
+ restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.EXACT);\r
+ break;\r
+ case ANYWHERE:\r
+ restriction = Restrictions.ilike(propertyName, queryString, org.hibernate.criterion.MatchMode.ANYWHERE);\r
+ break;\r
+ default:\r
+ throw new RuntimeException("Unknown MatchMode: " + matchMode.name());\r
+ }\r
+ }\r
+ return restriction;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ @Override\r
+ public long count(Class<? extends T> type, List<Restriction<?>> restrictions) {\r
+\r
+ Criteria criteria = createCriteria(type, restrictions, false);\r
+\r
+ criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
+\r
+ return (Long) criteria.uniqueResult();\r
+\r
+ }\r
+\r
/**\r
* @param uuids\r
* @param pageSize\r
* @param propertyName\r
* @return\r
*/\r
- private Criteria prepareList(Collection<?> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, String propertyName) {\r
- Criteria criteria = getSession().createCriteria(type);\r
+ private Criteria prepareList(Class<? extends T> clazz, Collection<?> uuids, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,\r
+ String propertyName) {\r
+ if (clazz == null){\r
+ clazz = type;\r
+ }\r
+ Criteria criteria = getSession().createCriteria(clazz);\r
criteria.add(Restrictions.in(propertyName, uuids));\r
\r
- if(pageSize != null) {\r
+ if (pageSize != null) {\r
criteria.setMaxResults(pageSize);\r
- if(pageNumber != null) {\r
+ if (pageNumber != null) {\r
criteria.setFirstResult(pageNumber * pageSize);\r
} else {\r
criteria.setFirstResult(0);\r
}\r
}\r
\r
- if(orderHints == null) {\r
+ if (orderHints == null) {\r
orderHints = OrderHint.defaultOrderHintsFor(type);\r
}\r
addOrder(criteria, orderHints);\r
return criteria;\r
}\r
\r
+ /**\r
+ * @param clazz\r
+ * @return\r
+ */\r
+ private Criteria criterionForType(Class<? extends T> clazz) {\r
+ return getSession().createCriteria(entityType(clazz));\r
+ }\r
\r
- protected List<T> findByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
- Criteria criteria = null;\r
-\r
- if(clazz == null) {\r
- criteria = getSession().createCriteria(type);\r
+ protected Class<? extends T> entityType(Class<? extends T> clazz){\r
+ if (clazz != null) {\r
+ return clazz;\r
} else {\r
- criteria = getSession().createCriteria(clazz);\r
- }\r
-\r
- if (queryString != null) {\r
- if(matchmode == null) {\r
- criteria.add(Restrictions.ilike(param, queryString));\r
- } else if(matchmode == MatchMode.BEGINNING) {\r
- criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));\r
- } else if(matchmode == MatchMode.END) {\r
- criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));\r
- } else if(matchmode == MatchMode.EXACT) {\r
- criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));\r
- } else {\r
- criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));\r
- }\r
+ return type;\r
}\r
-\r
- addCriteria(criteria, criterion);\r
-\r
- if(pageSize != null) {\r
- criteria.setMaxResults(pageSize);\r
- if(pageNumber != null) {\r
- criteria.setFirstResult(pageNumber * pageSize);\r
- } else {\r
- criteria.setFirstResult(0);\r
- }\r
- }\r
-\r
- addOrder(criteria, orderHints);\r
-\r
- @SuppressWarnings("unchecked")\r
- List<T> result = criteria.list();\r
- defaultBeanInitializer.initializeAll(result, propertyPaths);\r
- return result;\r
}\r
\r
@Override\r
public T load(UUID uuid) {\r
T bean = findByUuid(uuid);\r
- if(bean == null){\r
+ if (bean == null) {\r
return null;\r
}\r
defaultBeanInitializer.load(bean);\r
}\r
\r
@Override\r
- public T load(int id, List<String> propertyPaths){\r
+ public T load(int id, List<String> propertyPaths) {\r
T bean = findById(id);\r
- if(bean == null){\r
+ if (bean == null) {\r
return bean;\r
}\r
defaultBeanInitializer.initialize(bean, propertyPaths);\r
}\r
\r
@Override\r
- public T load(UUID uuid, List<String> propertyPaths){\r
- T bean = findByUuid(uuid);\r
- if(bean == null){\r
+ public T loadWithoutInitializing(int id){\r
+ return this.getSession().load(type, id);\r
+ }\r
+\r
+ @Override\r
+ public T load(UUID uuid, List<String> propertyPaths) {\r
+ return this.load(uuid, INCLUDE_UNPUBLISHED, propertyPaths);\r
+ }\r
+\r
+ protected T load(UUID uuid, boolean includeUnpublished, List<String> propertyPaths) {\r
+ T bean = findByUuid(uuid, includeUnpublished);\r
+ if (bean == null) {\r
return bean;\r
}\r
defaultBeanInitializer.initialize(bean, propertyPaths);\r
\r
@Override\r
public Boolean exists(UUID uuid) {\r
- if (findByUuid(uuid)==null){\r
+ if (findByUuid(uuid) == null) {\r
return false;\r
}\r
return true;\r
}\r
\r
@Override\r
- public int count() {\r
+ public long count() {\r
return count(type);\r
}\r
\r
@Override\r
- public int count(Class<? extends T> clazz) {\r
+ public long count(Class<? extends T> clazz) {\r
Session session = getSession();\r
Criteria criteria = null;\r
- if(clazz == null) {\r
+ if (clazz == null) {\r
criteria = session.createCriteria(type);\r
} else {\r
criteria = session.createCriteria(clazz);\r
}\r
criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
\r
- //since hibernate 4 (or so) uniqueResult returns Long, not Integer, therefore needs\r
- //to be casted. Think about returning long rather then int!\r
- return ((Number) criteria.uniqueResult()).intValue();\r
+ // since hibernate 4 (or so) uniqueResult returns Long, not Integer,\r
+ // therefore needs\r
+ // to be casted. Think about returning long rather then int!\r
+ return (long) criteria.uniqueResult();\r
}\r
\r
@Override\r
}\r
\r
@Override\r
- public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, List<String> propertyPaths) {\r
+ public List<Object[]> group(Class<? extends T> clazz, Integer limit, Integer start, List<Grouping> groups,\r
+ List<String> propertyPaths) {\r
\r
Criteria criteria = null;\r
- if(clazz == null){\r
- criteria = getSession().createCriteria(type);\r
- } else {\r
- criteria = getSession().createCriteria(clazz);\r
- }\r
+ criteria = criterionForType(clazz);\r
\r
- addGroups(criteria,groups);\r
+ addGroups(criteria, groups);\r
\r
- if(limit != null) {\r
+ if (limit != null) {\r
criteria.setFirstResult(start);\r
criteria.setMaxResults(limit);\r
}\r
\r
@SuppressWarnings("unchecked")\r
- List<Object[]> result = criteria.list();\r
+ List<Object[]> result = criteria.list();\r
\r
- if(propertyPaths != null && !propertyPaths.isEmpty()) {\r
- for(Object[] objects : result) {\r
- defaultBeanInitializer.initialize(objects[0], propertyPaths);\r
- }\r
+ if (propertyPaths != null && !propertyPaths.isEmpty()) {\r
+ for (Object[] objects : result) {\r
+ defaultBeanInitializer.initialize(objects[0], propertyPaths);\r
+ }\r
}\r
\r
return result;\r
}\r
\r
- protected void countGroups(DetachedCriteria criteria,List<Grouping> groups) {\r
- if(groups != null){\r
-\r
+ protected void countGroups(DetachedCriteria criteria, List<Grouping> groups) {\r
+ if (groups != null) {\r
\r
- Map<String,String> aliases = new HashMap<String,String>();\r
+ Map<String, String> aliases = new HashMap<String, String>();\r
\r
- for(Grouping grouping : groups) {\r
- if(grouping.getAssociatedObj() != null) {\r
+ for (Grouping grouping : groups) {\r
+ if (grouping.getAssociatedObj() != null) {\r
String alias = null;\r
- if((alias = aliases.get(grouping.getAssociatedObj())) == null) {\r
+ if ((alias = aliases.get(grouping.getAssociatedObj())) == null) {\r
alias = grouping.getAssociatedObjectAlias();\r
aliases.put(grouping.getAssociatedObj(), alias);\r
- criteria.createAlias(grouping.getAssociatedObj(),alias);\r
+ criteria.createAlias(grouping.getAssociatedObj(), alias);\r
}\r
}\r
}\r
\r
ProjectionList projectionList = Projections.projectionList();\r
\r
- for(Grouping grouping : groups) {\r
+ for (Grouping grouping : groups) {\r
grouping.addProjection(projectionList);\r
}\r
criteria.setProjection(projectionList);\r
}\r
}\r
\r
- protected void addGroups(Criteria criteria,List<Grouping> groups) {\r
- if(groups != null){\r
+ protected void addGroups(Criteria criteria, List<Grouping> groups) {\r
+ if (groups != null) {\r
\r
+ Map<String, String> aliases = new HashMap<String, String>();\r
\r
- Map<String,String> aliases = new HashMap<String,String>();\r
-\r
- for(Grouping grouping : groups) {\r
- if(grouping.getAssociatedObj() != null) {\r
+ for (Grouping grouping : groups) {\r
+ if (grouping.getAssociatedObj() != null) {\r
String alias = null;\r
- if((alias = aliases.get(grouping.getAssociatedObj())) == null) {\r
+ if ((alias = aliases.get(grouping.getAssociatedObj())) == null) {\r
alias = grouping.getAssociatedObjectAlias();\r
aliases.put(grouping.getAssociatedObj(), alias);\r
- criteria.createAlias(grouping.getAssociatedObj(),alias);\r
+ criteria.createAlias(grouping.getAssociatedObj(), alias);\r
}\r
}\r
}\r
\r
ProjectionList projectionList = Projections.projectionList();\r
\r
- for(Grouping grouping : groups) {\r
+ for (Grouping grouping : groups) {\r
grouping.addProjection(projectionList);\r
}\r
criteria.setProjection(projectionList);\r
\r
- for(Grouping grouping : groups) {\r
+ for (Grouping grouping : groups) {\r
grouping.addOrder(criteria);\r
\r
}\r
}\r
}\r
\r
- protected void addCriteria(Criteria criteria, List<Criterion> criterion) {\r
- if(criterion != null) {\r
- for(Criterion c : criterion) {\r
- criteria.add(c);\r
- }\r
- }\r
-\r
- }\r
-\r
- protected void addOrder(FullTextQuery fullTextQuery, List<OrderHint> orderHints) {\r
- //FIXME preliminary hardcoded type:\r
- SortField.Type type = SortField.Type.STRING;\r
-\r
- if(orderHints != null && !orderHints.isEmpty()) {\r
- org.apache.lucene.search.Sort sort = new Sort();\r
- SortField[] sortFields = new SortField[orderHints.size()];\r
- for(int i = 0; i < orderHints.size(); i++) {\r
- OrderHint orderHint = orderHints.get(i);\r
- switch(orderHint.getSortOrder()) {\r
- case ASCENDING:\r
- sortFields[i] = new SortField(orderHint.getPropertyName(), type, true);\r
- break;\r
- case DESCENDING:\r
- default:\r
- sortFields[i] = new SortField(orderHint.getPropertyName(), type, false);\r
-\r
- }\r
- }\r
- sort.setSort(sortFields);\r
- fullTextQuery.setSort(sort);\r
-\r
- }\r
- }\r
-\r
@Override\r
public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {\r
- return list(limit,start,orderHints,null);\r
+ return list(limit, start, orderHints, null);\r
}\r
\r
@Override\r
public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
Criteria criteria = getSession().createCriteria(type);\r
- if(limit != null) {\r
+ if (limit != null) {\r
criteria.setFirstResult(start);\r
criteria.setMaxResults(limit);\r
}\r
\r
- addOrder(criteria,orderHints);\r
+ addOrder(criteria, orderHints);\r
@SuppressWarnings("unchecked")\r
- List<T> results = criteria.list();\r
+ List<T> results = criteria.list();\r
\r
defaultBeanInitializer.initializeAll(results, propertyPaths);\r
return results;\r
}\r
\r
@Override\r
- public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+ public <S extends T> List<S> list(Class<S> clazz, Integer limit, Integer start, List<OrderHint> orderHints,\r
+ List<String> propertyPaths) {\r
Criteria criteria = null;\r
- if(clazz == null) {\r
+ if (clazz == null) {\r
criteria = getSession().createCriteria(type);\r
} else {\r
criteria = getSession().createCriteria(clazz);\r
}\r
\r
- if(limit != null) {\r
- if(start != null) {\r
- criteria.setFirstResult(start);\r
- } else {\r
- criteria.setFirstResult(0);\r
- }\r
- criteria.setMaxResults(limit);\r
- }\r
+ addLimitAndStart(criteria, limit, start);\r
\r
- addOrder(criteria,orderHints);\r
+ addOrder(criteria, orderHints);\r
\r
@SuppressWarnings("unchecked")\r
- List<S> results = criteria.list();\r
+ List<S> results = criteria.list();\r
\r
defaultBeanInitializer.initializeAll(results, propertyPaths);\r
return results;\r
}\r
\r
-\r
public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start, List<OrderHint> orderHints) {\r
- return list(type,limit,start,orderHints,null);\r
+ return list(type, limit, start, orderHints, null);\r
}\r
\r
@Override\r
public <S extends T> List<S> list(Class<S> type, Integer limit, Integer start) {\r
- return list(type,limit,start,null,null);\r
- }\r
-\r
- @Override\r
- public List<T> rows(String tableName, int limit, int start) {\r
- Query query = getSession().createQuery("from " + tableName + " order by uuid");\r
- query.setFirstResult(start);\r
- query.setMaxResults(limit);\r
- @SuppressWarnings("unchecked")\r
- List<T> result = query.list();\r
- return result;\r
+ return list(type, limit, start, null, null);\r
}\r
\r
@Override\r
return type;\r
}\r
\r
- protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){\r
- if(pageSize != null) {\r
+ protected void setPagingParameter(Query query, Integer pageSize, Integer pageIndex) {\r
+ if (pageSize != null) {\r
query.setMaxResults(pageSize);\r
- if(pageNumber != null) {\r
- query.setFirstResult(pageNumber * pageSize);\r
+ if (pageIndex != null) {\r
+ query.setFirstResult(pageIndex * pageSize);\r
} else {\r
query.setFirstResult(0);\r
}\r
}\r
}\r
\r
- protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageNumber){\r
- if(pageSize != null) {\r
+ protected void setPagingParameter(AuditQuery query, Integer pageSize, Integer pageIndex) {\r
+ if (pageSize != null) {\r
query.setMaxResults(pageSize);\r
- if(pageNumber != null) {\r
- query.setFirstResult(pageNumber * pageSize);\r
+ if (pageIndex != null) {\r
+ query.setFirstResult(pageIndex * pageSize);\r
} else {\r
query.setFirstResult(0);\r
}\r
}\r
\r
@Override\r
- public int count(T example, Set<String> includeProperties) {\r
+ public long count(T example, Set<String> includeProperties) {\r
Criteria criteria = getSession().createCriteria(example.getClass());\r
- addExample(criteria,example,includeProperties);\r
+ addExample(criteria, example, includeProperties);\r
\r
criteria.setProjection(Projections.rowCount());\r
- return ((Number)criteria.uniqueResult()).intValue();\r
+ return (Long) criteria.uniqueResult();\r
}\r
\r
protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {\r
- if(includeProperties != null && !includeProperties.isEmpty()) {\r
+ if (includeProperties != null && !includeProperties.isEmpty()) {\r
criteria.add(Example.create(example).setPropertySelector(new PropertySelectorImpl(includeProperties)));\r
ClassMetadata classMetadata = getSession().getSessionFactory().getClassMetadata(example.getClass());\r
- for(String property : includeProperties) {\r
- Type type = classMetadata.getPropertyType(property);\r
- if(type.isEntityType()) {\r
+ for (String property : includeProperties) {\r
+ Type type = classMetadata.getPropertyType(property);\r
+ if (type.isEntityType()) {\r
try {\r
Field field = ReflectionUtils.findField(example.getClass(), property);\r
field.setAccessible(true);\r
- Object value = field.get(example);\r
- if(value != null) {\r
- criteria.add(Restrictions.eq(property,value));\r
+ Object value = field.get(example);\r
+ if (value != null) {\r
+ criteria.add(Restrictions.eq(property, value));\r
} else {\r
criteria.add(Restrictions.isNull(property));\r
}\r
} catch (SecurityException se) {\r
- throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, se);\r
+ throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,\r
+ se);\r
} catch (HibernateException he) {\r
- throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);\r
+ throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,\r
+ he);\r
} catch (IllegalArgumentException iae) {\r
- throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);\r
+ throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,\r
+ iae);\r
} catch (IllegalAccessException ie) {\r
- throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);\r
+ throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property,\r
+ ie);\r
}\r
-\r
}\r
}\r
} else {\r
}\r
}\r
\r
+ /**\r
+ *\r
+ * NOTE: We can't reuse\r
+ * {@link #list(Class, String, Object, MatchMode, Integer, Integer, List, List)\r
+ * here due to different default behavior of the <code>matchmode</code>\r
+ * parameter.\r
+ *\r
+ * @param clazz\r
+ * @param param\r
+ * @param queryString\r
+ * @param matchmode\r
+ * @param criterion\r
+ * @param pageSize\r
+ * @param pageNumber\r
+ * @param orderHints\r
+ * @param propertyPaths\r
+ * @return\r
+ */\r
+ @Override\r
+ public <S extends T> List<S> findByParam(Class<S> clazz, String param, String queryString, MatchMode matchmode,\r
+ List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,\r
+ List<String> propertyPaths) {\r
+ Set<String> stringSet = new HashSet<>();\r
+ stringSet.add(param);\r
+ return this.findByParam(clazz, stringSet, queryString, matchmode,\r
+ criterion, pageSize, pageNumber, orderHints,\r
+ propertyPaths);\r
+ }\r
\r
- protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {\r
- Criteria criteria = null;\r
+ @Override\r
+ public <S extends T> List<S> findByParam(Class<S> clazz, Set<String> params, String queryString, MatchMode matchmode,\r
+ List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,\r
+ List<String> propertyPaths) {\r
+\r
+ Criteria criteria = criterionForType(clazz);\r
+\r
+ if (queryString != null) {\r
+ Set<Criterion> criterions = new HashSet<>();\r
+ for (String param: params){\r
+ Criterion crit;\r
+ if (matchmode == null) {\r
+ crit = Restrictions.ilike(param, queryString);\r
+ } else if (matchmode == MatchMode.BEGINNING) {\r
+ crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START);\r
+ } else if (matchmode == MatchMode.END) {\r
+ crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END);\r
+ } else if (matchmode == MatchMode.EXACT) {\r
+ crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT);\r
+ } else {\r
+ crit = Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE);\r
+ }\r
+ criterions.add(crit);\r
+ }\r
+ if (criterions.size()>1){\r
+ Iterator<Criterion> critIterator = criterions.iterator();\r
+ Disjunction disjunction = Restrictions.disjunction();\r
+ while (critIterator.hasNext()){\r
+ disjunction.add(critIterator.next());\r
+ }\r
+\r
+ criteria.add(disjunction);\r
+\r
+ }else{\r
+ if (!criterions.isEmpty()){\r
+ criteria.add(criterions.iterator().next());\r
+ }\r
+ }\r
\r
- if(clazz == null) {\r
- criteria = getSession().createCriteria(type);\r
- } else {\r
- criteria = getSession().createCriteria(clazz);\r
}\r
\r
+ addCriteria(criteria, criterion);\r
+\r
+ if (pageSize != null) {\r
+ criteria.setMaxResults(pageSize);\r
+ if (pageNumber != null) {\r
+ criteria.setFirstResult(pageNumber * pageSize);\r
+ } else {\r
+ criteria.setFirstResult(0);\r
+ }\r
+ }\r
+\r
+ addOrder(criteria, orderHints);\r
+\r
+ @SuppressWarnings("unchecked")\r
+ List<S> result = criteria.list();\r
+ defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+ return result;\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param clazz\r
+ * @param param\r
+ * @param queryString\r
+ * @param matchmode\r
+ * @param criterion\r
+ * @return\r
+ */\r
+ @Override\r
+ public long countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode,\r
+ List<Criterion> criterion) {\r
+\r
+ Criteria criteria = null;\r
+\r
+ criteria = criterionForType(clazz);\r
+\r
if (queryString != null) {\r
- if(matchmode == null) {\r
+ if (matchmode == null) {\r
criteria.add(Restrictions.ilike(param, queryString));\r
- } else if(matchmode == MatchMode.BEGINNING) {\r
+ } else if (matchmode == MatchMode.BEGINNING) {\r
criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.START));\r
- } else if(matchmode == MatchMode.END) {\r
+ } else if (matchmode == MatchMode.END) {\r
criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.END));\r
- } else if(matchmode == MatchMode.EXACT) {\r
+ } else if (matchmode == MatchMode.EXACT) {\r
criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.EXACT));\r
} else {\r
criteria.add(Restrictions.ilike(param, queryString, org.hibernate.criterion.MatchMode.ANYWHERE));\r
\r
criteria.setProjection(Projections.rowCount());\r
\r
-// List<T> result = criteria.list();\r
- return ((Number)criteria.uniqueResult()).intValue();\r
+ return (Long) criteria.uniqueResult();\r
+ }\r
+\r
+ /**\r
+ * Creates a criteria query for the CDM <code>type</code> either for counting or listing matching entities.\r
+ * <p>\r
+ * The set of matching entities can be restricted by passing a list of {@link Restriction} objects.\r
+ * Restrictions can logically combined:\r
+ <pre>\r
+ Arrays.asList(\r
+ new Restriction<String>("titleCache", MatchMode.ANYWHERE, "foo"),\r
+ new Restriction<String>("institute.name", Operator.OR, MatchMode.BEGINNING, "Bar")\r
+ );\r
+ </pre>\r
+ * The first Restriction in the example above by default has the <code>Operator.AND</code> which will be\r
+ * ignored since this is the first restriction. The <code>Operator</code> of further restrictions in the\r
+ * list are used to combine with the previous restriction.\r
+ *\r
+ * @param type\r
+ * @param restrictions\r
+ * @param doCount\r
+ * @return\r
+ */\r
+ protected Criteria createCriteria(Class<? extends T> type, List<Restriction<?>> restrictions, boolean doCount) {\r
+\r
+ DetachedCriteria idsOnlyCriteria = DetachedCriteria.forClass(entityType(type));\r
+ idsOnlyCriteria.setProjection(Projections.distinct(Projections.id()));\r
+\r
+ addRestrictions(restrictions, idsOnlyCriteria);\r
+\r
+ Criteria criteria = criterionForType(type);\r
+ criteria.add(Subqueries.propertyIn("id", idsOnlyCriteria));\r
+\r
+ if(doCount){\r
+ criteria.setProjection(Projections.rowCount());\r
+ } else {\r
+ idsOnlyCriteria.setProjection(Projections.distinct(Projections.property("id")));\r
+ }\r
+\r
+ return criteria;\r
}\r
\r
\r
@Override\r
- public List<T> list(T example, Set<String> includeProperties, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
- Criteria criteria = getSession().createCriteria(example.getClass());\r
- addExample(criteria,example,includeProperties);\r
+ public <S extends T> List<S> findByParamWithRestrictions(Class<S> clazz, String param, String queryString,\r
+ MatchMode matchmode, List<Restriction<?>> restrictions, Integer pageSize, Integer pageNumber,\r
+ List<OrderHint> orderHints, List<String> propertyPaths) {\r
+\r
+ List<Restriction<?>> allRestrictions = new ArrayList<>();\r
+ allRestrictions.add(new Restriction<String>(param, matchmode, queryString));\r
+ if(restrictions != null){\r
+ allRestrictions.addAll(restrictions);\r
+ }\r
+ Criteria criteria = createCriteria(clazz, allRestrictions, false);\r
\r
- if(limit != null) {\r
- if(start != null) {\r
- criteria.setFirstResult(start);\r
+ if (pageSize != null) {\r
+ criteria.setMaxResults(pageSize);\r
+ if (pageNumber != null) {\r
+ criteria.setFirstResult(pageNumber * pageSize);\r
} else {\r
criteria.setFirstResult(0);\r
}\r
- criteria.setMaxResults(limit);\r
}\r
\r
- addOrder(criteria,orderHints);\r
+ addOrder(criteria, orderHints);\r
\r
@SuppressWarnings("unchecked")\r
- List<T> results = criteria.list();\r
+ List<S> result = criteria.list();\r
+ defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+ return result;\r
+\r
+ }\r
+\r
+ @Override\r
+ public long countByParamWithRestrictions(Class<? extends T> clazz, String param, String queryString,\r
+ MatchMode matchmode, List<Restriction<?>> restrictions) {\r
+\r
+ List<Restriction<?>> allRestrictions = new ArrayList<>();\r
+ allRestrictions.add(new Restriction<String>(param, matchmode, queryString));\r
+ if(restrictions != null){\r
+ allRestrictions.addAll(restrictions);\r
+ }\r
+ Criteria criteria = createCriteria(clazz, allRestrictions, true);\r
+\r
+ return (Long) criteria.uniqueResult();\r
+ }\r
+\r
+ @Override\r
+ public <S extends T> List<S> list(S example, Set<String> includeProperties, Integer limit, Integer start,\r
+ List<OrderHint> orderHints, List<String> propertyPaths) {\r
+ Criteria criteria = getSession().createCriteria(example.getClass());\r
+ addExample(criteria, example, includeProperties);\r
+\r
+ addLimitAndStart(criteria, limit, start);\r
+\r
+ addOrder(criteria, orderHints);\r
+\r
+ @SuppressWarnings("unchecked")\r
+ List<S> results = criteria.list();\r
defaultBeanInitializer.initializeAll(results, propertyPaths);\r
return results;\r
}\r
}\r
\r
@Override\r
- public boolean include(Object propertyValue, String propertyName, Type type) {\r
- if(includeProperties.contains(propertyName)) {\r
+ public boolean include(Object propertyValue, String propertyName, Type type) {\r
+ if (includeProperties.contains(propertyName)) {\r
return true;\r
} else {\r
return false;\r
}\r
\r
}\r
-}\r
\r
+ private class CriterionWithOperator {\r
+\r
+ Restriction.Operator operator;\r
+ Criterion criterion;\r
+\r
+\r
+ public CriterionWithOperator(Operator operator, Criterion criterion) {\r
+ super();\r
+ this.operator = operator;\r
+ this.criterion = criterion;\r
+ }\r
+\r
+\r
+ }\r
+\r
+ /**\r
+ * Returns a Criteria for the given {@link Class class} or, if\r
+ * <code>null</code>, for the base {@link Class class} of this DAO.\r
+ *\r
+ * @param clazz\r
+ * @return the Criteria\r
+ */\r
+ protected Criteria getCriteria(Class<? extends CdmBase> clazz) {\r
+ Criteria criteria = null;\r
+ if (clazz == null) {\r
+ criteria = getSession().createCriteria(type);\r
+ } else {\r
+ criteria = getSession().createCriteria(clazz);\r
+ }\r
+ return criteria;\r
+ }\r
+\r
+ /**\r
+ * @param clazz\r
+ * @param auditEvent\r
+ * @return\r
+ */\r
+ protected AuditQuery makeAuditQuery(Class<? extends CdmBase> clazz, AuditEvent auditEvent) {\r
+ AuditQuery query = null;\r
+\r
+ if (clazz == null) {\r
+ query = getAuditReader().createQuery().forEntitiesAtRevision(type, auditEvent.getRevisionNumber());\r
+ } else {\r
+ query = getAuditReader().createQuery().forEntitiesAtRevision(clazz, auditEvent.getRevisionNumber());\r
+ }\r
+ return query;\r
+ }\r
+\r
+ protected AuditReader getAuditReader() {\r
+ return AuditReaderFactory.get(getSession());\r
+ }\r
+}\r