moving all beaninitializer classes to new package 'eu.etaxonomy.cdm.persistence.dao...
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / common / CdmEntityDaoBase.java
index c759fa28b09559356ae44ac13e045d939d20681c..c802dcf8de96d941e5add64971ca691e76817c60 100644 (file)
@@ -1,8 +1,8 @@
 /**\r
 * Copyright (C) 2007 EDIT\r
-* European Distributed Institute of Taxonomy \r
+* European Distributed Institute of Taxonomy\r
 * http://www.e-taxonomy.eu\r
-* \r
+*\r
 * The contents of this file are subject to the Mozilla Public License Version 1.1\r
 * See LICENSE.TXT at the top of this package for the full license terms.\r
 */\r
@@ -10,6 +10,7 @@
 package eu.etaxonomy.cdm.persistence.dao.hibernate.common;\r
 \r
 import java.lang.reflect.Field;\r
+import java.util.ArrayList;\r
 import java.util.Collection;\r
 import java.util.HashMap;\r
 import java.util.Iterator;\r
@@ -21,6 +22,7 @@ import java.util.UUID;
 import org.apache.log4j.Logger;\r
 import org.apache.lucene.search.Sort;\r
 import org.apache.lucene.search.SortField;\r
+import org.apache.lucene.util.Version;\r
 import org.hibernate.Criteria;\r
 import org.hibernate.HibernateException;\r
 import org.hibernate.LockMode;\r
@@ -48,11 +50,12 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Repository;\r
 import org.springframework.util.ReflectionUtils;\r
 \r
+import eu.etaxonomy.cdm.config.Configuration;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.common.User;\r
 import eu.etaxonomy.cdm.model.common.VersionableEntity;\r
-import eu.etaxonomy.cdm.persistence.dao.BeanInitializer;\r
 import eu.etaxonomy.cdm.persistence.dao.common.ICdmEntityDao;\r
+import eu.etaxonomy.cdm.persistence.dao.initializer.IBeanInitializer;\r
 import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadata;\r
 import eu.etaxonomy.cdm.persistence.hibernate.replace.ReferringObjectMetadataFactory;\r
 import eu.etaxonomy.cdm.persistence.query.Grouping;\r
@@ -66,683 +69,769 @@ import eu.etaxonomy.cdm.persistence.query.OrderHint;
  */\r
 @Repository\r
 public abstract class CdmEntityDaoBase<T extends CdmBase> extends DaoBase implements ICdmEntityDao<T> {\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 Class<T> type;\r
-       \r
-       @Autowired\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
+\r
+    protected Class<T> type;\r
+\r
+    protected Version version = Configuration.luceneVersion;\r
+\r
+    @Autowired\r
 //     @Qualifier("defaultBeanInitializer")\r
-       protected BeanInitializer defaultBeanInitializer;\r
-       \r
-       public void setDefaultBeanInitializer(BeanInitializer defaultBeanInitializer) {\r
-               this.defaultBeanInitializer = defaultBeanInitializer;\r
-       }\r
-\r
-       @Autowired\r
-       private ReferringObjectMetadataFactory referringObjectMetadataFactory;\r
-       \r
-       \r
-       public CdmEntityDaoBase(Class<T> type){\r
-               this.type = type;\r
-               logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");\r
-       }\r
-       \r
-       public void lock(T t, LockMode lockMode) {\r
-               getSession().lock(t, lockMode);\r
-       }\r
-       \r
-       public void refresh(T t, LockMode lockMode, List<String> propertyPaths) {\r
-               getSession().refresh(t, lockMode);\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
-               getSession().saveOrUpdate(cdmObj);\r
-               return cdmObj.getUuid();\r
-       }\r
-       \r
+    protected IBeanInitializer defaultBeanInitializer;\r
+\r
+    public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer) {\r
+        this.defaultBeanInitializer = defaultBeanInitializer;\r
+    }\r
+\r
+    @Autowired\r
+    private ReferringObjectMetadataFactory referringObjectMetadataFactory;\r
+\r
+\r
+    public CdmEntityDaoBase(Class<T> type){\r
+        this.type = type;\r
+        logger.debug("Creating DAO of type [" + type.getSimpleName() + "]");\r
+    }\r
+\r
+    @Override\r
+    public void lock(T t, LockMode lockMode) {\r
+        getSession().lock(t, lockMode);\r
+    }\r
+\r
+    @Override\r
+    public void refresh(T t, LockMode lockMode, List<String> propertyPaths) {\r
+        getSession().refresh(t, lockMode);\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
+        getSession().saveOrUpdate(cdmObj);\r
+        return cdmObj.getUuid();\r
+    }\r
+\r
     //TODO: Replace saveCdmObj() by saveCdmObject_\r
-       private UUID saveCdmObject_(T cdmObj){\r
-               getSession().saveOrUpdate(cdmObj);\r
-               return cdmObj.getUuid();\r
-       }\r
-       \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
-       public Map<UUID, T> saveAll(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
-               }\r
-\r
-               Map<UUID, T> resultMap = new HashMap<UUID, T>();\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
-                       T cdmObj = iterator.next();\r
-                       UUID uuid = saveCdmObject_(cdmObj);\r
-                       if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
-                       resultMap.put(uuid, cdmObj);\r
-                       i++;\r
-                       if ( (i % flushAfterNo) == 0){\r
-                               try{\r
-                                       if (logger.isDebugEnabled()){logger.debug("flush");}\r
-                                       flush();\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
-\r
-               if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
-               return resultMap;\r
-       }\r
-       \r
+    //TODO: why does this use saveCdmObject_ which actually savesOrUpdateds data ?\r
+    @Override\r
+    public Map<UUID, T> saveAll(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
+        }\r
+\r
+        Map<UUID, T> resultMap = new HashMap<UUID, T>();\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
+            T cdmObj = iterator.next();\r
+            UUID uuid = saveCdmObject_(cdmObj);\r
+            if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
+            resultMap.put(uuid, cdmObj);\r
+            i++;\r
+            if ( (i % flushAfterNo) == 0){\r
+                try{\r
+                    if (logger.isDebugEnabled()){logger.debug("flush");}\r
+                    flush();\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
+\r
+        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
+        return resultMap;\r
+    }\r
+\r
     private UUID saveOrUpdateCdmObject(T cdmObj){\r
-               getSession().saveOrUpdate(cdmObj);\r
-               return cdmObj.getUuid();\r
-       }\r
-    \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
-               }\r
-\r
-               Map<UUID, T> resultMap = new HashMap<UUID, T>();\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
-                       T cdmObj = iterator.next();\r
-                       UUID uuid = saveOrUpdateCdmObject(cdmObj);\r
-                       if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
-                       resultMap.put(uuid, cdmObj);\r
-                       i++;\r
-                       if ( (i % flushAfterNo) == 0){\r
-                               try{\r
-                                       if (logger.isDebugEnabled()){logger.debug("flush");}\r
-                                       flush();\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
-\r
-               if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
-               return resultMap;\r
-       }\r
-       \r
-       \r
-       \r
-       \r
-       public T replace(T x, T y) {\r
-               if(x.equals(y)) {\r
-                       return y;\r
-               }\r
-               \r
-               Class commonClass = x.getClass();\r
-               if(y != null) {\r
+        getSession().saveOrUpdate(cdmObj);\r
+        return cdmObj.getUuid();\r
+    }\r
+\r
+    @Override\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
+        }\r
+\r
+        Map<UUID, T> resultMap = new HashMap<UUID, T>();\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
+            T cdmObj = iterator.next();\r
+            UUID uuid = saveOrUpdateCdmObject(cdmObj);\r
+            if (logger.isDebugEnabled()){logger.debug("Save cdmObj: " + (cdmObj == null? null: cdmObj.toString()));}\r
+            resultMap.put(uuid, cdmObj);\r
+            i++;\r
+            if ( (i % flushAfterNo) == 0){\r
+                try{\r
+                    if (logger.isDebugEnabled()){logger.debug("flush");}\r
+                    flush();\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
+\r
+        if ( logger.isInfoEnabled() ){logger.info("Saved " + i + " objects" );}\r
+        return resultMap;\r
+    }\r
+\r
+\r
+\r
+\r
+    @Override\r
+    public T replace(T x, T 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
-                           throw new RuntimeException();\r
-                   }\r
-                   commonClass = commonClass.getSuperclass();\r
+                if(commonClass.equals(type)) {\r
+                    throw new RuntimeException();\r
+                }\r
+                commonClass = commonClass.getSuperclass();\r
             }\r
-               }\r
+        }\r
+\r
+        getSession().merge(x);\r
 \r
-               getSession().merge(x);\r
-               \r
         Set<ReferringObjectMetadata> referringObjectMetas = referringObjectMetadataFactory.get(x.getClass());\r
-        \r
+\r
         for(ReferringObjectMetadata referringObjectMetadata : referringObjectMetas) {\r
-          \r
-          List<CdmBase> referringObjects = referringObjectMetadata.getReferringObjects(x,getSession());\r
-         \r
+\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
-              \r
-                       } catch (IllegalArgumentException e) {\r
-                               throw new RuntimeException(e.getMessage(),e);\r
-                       } catch (IllegalAccessException e) {\r
-                               throw new RuntimeException(e.getMessage(),e);\r
-                       }\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
+            }\r
           }\r
         }\r
         return y;\r
     }\r
 \r
-       public Session getSession() throws DataAccessException {\r
-               return super.getSession();\r
-       }\r
-\r
-       public void clear() throws DataAccessException {\r
-               Session session = getSession();\r
-               session.clear();\r
-               if (logger.isDebugEnabled()){logger.debug("dao clear end");}\r
-       }\r
-\r
-       public UUID merge(T transientObject) throws DataAccessException {\r
-               Session session = getSession();\r
-               session.merge(transientObject);\r
-               if (logger.isDebugEnabled()){logger.debug("dao merge end");}\r
-               return transientObject.getUuid();\r
-       }\r
-       \r
-       public UUID saveOrUpdate(T transientObject) throws DataAccessException  {\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
-                       Session session = getSession();\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
-                               } \r
-                       }\r
-                       session.saveOrUpdate(transientObject);\r
-                       if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}\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(e.getMessage());\r
-                       \r
-                       e.printStackTrace();\r
-                       throw e;\r
-               } catch (HibernateException e) {\r
-                       \r
-                       e.printStackTrace();\r
-                       throw e;\r
-               }\r
-       }\r
-\r
-       public UUID save(T newInstance) throws DataAccessException {\r
-               getSession().save(newInstance);\r
-               return newInstance.getUuid();\r
-       }\r
-       \r
-       public UUID update(T transientObject) throws DataAccessException {\r
-               getSession().update(transientObject);\r
-               return transientObject.getUuid();\r
-       }\r
-       \r
-       public UUID refresh(T persistentObject) throws DataAccessException {\r
-               getSession().refresh(persistentObject);\r
-               return persistentObject.getUuid();\r
-       }\r
-       \r
-       public UUID delete(T persistentObject) throws DataAccessException {\r
-               if (persistentObject == null){\r
-                       logger.warn(type.getName() + " was 'null'");\r
-                       return null;\r
-               }\r
-               \r
-               // Merge the object in if it is detached\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
-               getSession().merge(persistentObject);\r
-               getSession().delete(persistentObject);\r
-               return persistentObject.getUuid();\r
-       }\r
-\r
-       public T findById(int id) throws DataAccessException {\r
-               return (T) getSession().get(type, id);\r
-       }\r
-       public List<T> findById(Set<Integer> idSet) throws DataAccessException {\r
-               Session session = getSession();\r
-               String hql = "from " + type.getSimpleName() + " type where type.id in ( :idSet )" ;\r
-               Query query = session.createQuery(hql);\r
-               query.setParameterList("idSet", idSet);\r
-               List<T> results = query.list();\r
-               return results;                 \r
-       }\r
-       public T findByUuid(UUID uuid) 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
-               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
-       }\r
-       \r
-       public List<T> findByUuid(Set<UUID> uuidSet) throws DataAccessException {\r
-               Session session = getSession();\r
-               String hql = "from " + type.getSimpleName() + " type where type.uuid in ( :uuidSet )" ;\r
-               Query query = session.createQuery(hql);\r
-               query.setParameterList("uuidSet", uuidSet);\r
-               List<T> results = query.list();\r
-               return results;                 \r
-       }\r
-       \r
+    @Override\r
+    public Session getSession() throws DataAccessException {\r
+        return super.getSession();\r
+    }\r
+\r
+    @Override\r
+    public void clear() throws DataAccessException {\r
+        Session session = getSession();\r
+        session.clear();\r
+        if (logger.isDebugEnabled()){logger.debug("dao clear end");}\r
+    }\r
+\r
+    @Override\r
+    public T merge(T transientObject) throws DataAccessException {\r
+        Session session = getSession();\r
+        T persistentObject = (T)session.merge(transientObject);\r
+        if (logger.isDebugEnabled()){logger.debug("dao merge end");}\r
+        return persistentObject;\r
+    }\r
+\r
+    @Override\r
+    public UUID saveOrUpdate(T transientObject) throws DataAccessException  {\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
+            Session session = getSession();\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
+                }\r
+            }\r
+            session.saveOrUpdate(transientObject);\r
+            if (logger.isDebugEnabled()){logger.debug("dao saveOrUpdate end");}\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(e.getMessage());\r
+\r
+            e.printStackTrace();\r
+            throw e;\r
+        } catch (HibernateException e) {\r
+\r
+            e.printStackTrace();\r
+            throw e;\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public UUID save(T newInstance) throws DataAccessException {\r
+        getSession().save(newInstance);\r
+        return newInstance.getUuid();\r
+    }\r
+\r
+    @Override\r
+    public UUID update(T transientObject) throws DataAccessException {\r
+        getSession().update(transientObject);\r
+        return transientObject.getUuid();\r
+    }\r
+\r
+    @Override\r
+    public UUID refresh(T persistentObject) throws DataAccessException {\r
+        getSession().refresh(persistentObject);\r
+        return persistentObject.getUuid();\r
+    }\r
+\r
+    @Override\r
+    public UUID delete(T persistentObject) throws DataAccessException {\r
+        if (persistentObject == null){\r
+            logger.warn(type.getName() + " was 'null'");\r
+            return null;\r
+        }\r
+\r
+        // Merge the object in if it is detached\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
+        getSession().merge(persistentObject);\r
+        getSession().delete(persistentObject);\r
+        return persistentObject.getUuid();\r
+    }\r
+\r
+    @Override\r
+    public T findById(int id) throws DataAccessException {\r
+        return (T) getSession().get(type, id);\r
+    }\r
+\r
+\r
+    @Override\r
+    public T findByUuid(UUID uuid) 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
+        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
+    }\r
+\r
+    @Override\r
+    public List<T> listByIds(Collection<Integer> ids,  Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) throws DataAccessException {\r
+\r
+        if (ids.isEmpty()) {\r
+            return new ArrayList<T>(0);\r
+        }\r
+\r
+        Criteria criteria = prepareList(ids, pageSize, pageNumber, orderHints, "id");\r
+\r
+        logger.debug(criteria.toString());\r
+\r
+         List<T> result = criteria.list();\r
+         defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+         return result;\r
+     }\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
+\r
+       Criteria criteria = prepareList(uuids, pageSize, pageNumber, orderHints, "uuid");\r
+\r
+        List<T> result = criteria.list();\r
+        defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+        return result;\r
+    }\r
+\r
+    /**\r
+     * @param uuids\r
+     * @param pageSize\r
+     * @param pageNumber\r
+     * @param orderHints\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
+        criteria.add(Restrictions.in(propertyName, uuids));\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
+        if(orderHints == null) {\r
+            orderHints = OrderHint.defaultOrderHintsFor(type);\r
+        }\r
+        addOrder(criteria, orderHints);\r
+        return criteria;\r
+    }\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
-       } 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
-       }\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
-       List<T> result = (List<T>)criteria.list();\r
-       defaultBeanInitializer.initializeAll(result, propertyPaths);\r
-       return result;\r
-    }\r
-       \r
-       public T load(UUID uuid) {\r
-               T bean = findByUuid(uuid);\r
-               if(bean == null) \r
-                       return null;\r
-               defaultBeanInitializer.load(bean);\r
-               \r
-               return bean;\r
-       }\r
-       \r
-\r
-       public T load(UUID uuid, List<String> propertyPaths){\r
-               T bean = findByUuid(uuid);\r
-               if(bean == null) \r
-                       return bean;\r
-               \r
-               defaultBeanInitializer.initialize(bean, propertyPaths);\r
-               \r
-               return bean;\r
-       }\r
-       \r
-       public List<T> load(Set<UUID> uuidSet, List<String> propertyPaths) throws DataAccessException{\r
-               List<T> list = findByUuid(uuidSet);\r
-               defaultBeanInitializer.initializeAll(list, propertyPaths);\r
-               return list;\r
-       }\r
-       \r
-       public Boolean exists(UUID uuid) {\r
-               if (findByUuid(uuid)==null){\r
-                       return false;\r
-               }\r
-               return true;\r
-       }\r
-       \r
-       public int count() {\r
-               return count(type);\r
-       }\r
-       \r
-       public int count(Class<? extends T> clazz) {\r
-               Session session = getSession();\r
-               Criteria criteria = 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
-               return (Integer) criteria.uniqueResult();\r
-       }\r
-\r
-       public List<T> list(Integer limit, Integer start) {\r
-               return list(limit, start, null); \r
-       }\r
-       \r
-       public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, 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
-               \r
-               addGroups(criteria,groups);\r
-               \r
-               if(limit != null) {\r
-                       criteria.setFirstResult(start);\r
-                       criteria.setMaxResults(limit);\r
-               }\r
-               \r
-               List<Object[]> result = (List<Object[]>)criteria.list();\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
-\r
-                       Map<String,String> aliases = new HashMap<String,String>();\r
-\r
-                       for(Grouping grouping : groups) {\r
-                               if(grouping.getAssociatedObj() != null) {\r
-                                       String alias = 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
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       ProjectionList projectionList = Projections.projectionList();\r
-\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
-\r
-\r
-                       Map<String,String> aliases = new HashMap<String,String>();\r
-\r
-                       for(Grouping grouping : groups) {\r
-                               if(grouping.getAssociatedObj() != null) {\r
-                                       String alias = 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
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       ProjectionList projectionList = Projections.projectionList();\r
-\r
-                       for(Grouping grouping : groups) {\r
-                               grouping.addProjection(projectionList);\r
-                       }\r
-                       criteria.setProjection(projectionList);\r
-                       \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
-               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(), true);\r
-                           break;\r
-                       case DESCENDING:\r
-                       default:\r
-                               sortFields[i] = new SortField(orderHint.getPropertyName(),false);\r
-                               \r
-                       }\r
-                   }\r
-                   sort.setSort(sortFields);\r
-                   fullTextQuery.setSort(sort);\r
-                   \r
-               }\r
-       }\r
-       \r
-       public List<T> list(Integer limit, Integer start, List<OrderHint> orderHints) {\r
-               return list(limit,start,orderHints,null);\r
-       }\r
-       \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
-                       criteria.setFirstResult(start);\r
-                       criteria.setMaxResults(limit);\r
-               }\r
-               \r
-               addOrder(criteria,orderHints);\r
-               List<T> results = (List<T>)criteria.list();\r
-               \r
-               defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-               return results;\r
-       }\r
-\r
-       public List<T> list(Class<? extends T> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-               Criteria criteria = 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
-               \r
-               addOrder(criteria,orderHints);\r
-               \r
-               List<T> results = (List<T>)criteria.list();\r
-               defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-               return results; \r
-       }\r
-       \r
-       public List<T> list(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints) {\r
-               return list(type,limit,start,orderHints,null);\r
-       }\r
-       \r
-       public List<T> list(Class<? extends T> type, Integer limit, Integer start) {\r
-               return list(type,limit,start,null,null);\r
-       }\r
-       \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
-               List<T> result = query.list();\r
-               return result;\r
-       }\r
-       \r
-       public Class<T> getType() {\r
-               return type;\r
-       }\r
-       \r
-       protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){\r
-               if(pageSize != null) {\r
-               query.setMaxResults(pageSize);\r
-                   if(pageNumber != null) {\r
-                       query.setFirstResult(pageNumber * 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
-               query.setMaxResults(pageSize);\r
-                   if(pageNumber != null) {\r
-                       query.setFirstResult(pageNumber * pageSize);\r
-                   } else {\r
-                       query.setFirstResult(0);\r
-                   }\r
-               }\r
-       }\r
-       \r
-       public int count(T example, Set<String> includeProperties) {\r
-               Criteria criteria = getSession().createCriteria(example.getClass());\r
-               addExample(criteria,example,includeProperties);\r
-               \r
-               criteria.setProjection(Projections.rowCount());\r
-               return (Integer)criteria.uniqueResult();\r
-       }\r
-       \r
-       protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {\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
-                                   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
-                                           } 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
-                                   } catch (HibernateException he) {\r
-                                           throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);\r
-                                   } catch (IllegalArgumentException iae) {\r
-                                           throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);\r
-                                   } catch (IllegalAccessException ie) {\r
-                                           throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);\r
-                                   }\r
-                       \r
-                       }\r
-                   }\r
-               } else {\r
-                       criteria.add(Example.create(example));\r
-               }\r
-       }\r
-       \r
-       \r
-       protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {\r
-       Criteria criteria = null;\r
-\r
-       if(clazz == null) {\r
-               criteria = getSession().createCriteria(type);\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
-       }\r
-       \r
-       addCriteria(criteria, criterion);\r
-       \r
-       criteria.setProjection(Projections.rowCount());         \r
-\r
-       List<T> result = criteria.list();\r
-       return (Integer)criteria.uniqueResult();\r
-       }\r
-\r
-       \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
-               \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
-               \r
-               addOrder(criteria,orderHints);\r
-               \r
-               List<T> results = (List<T>)criteria.list();\r
-               defaultBeanInitializer.initializeAll(results, propertyPaths);\r
-               return results; \r
-       }\r
-       \r
-       private class PropertySelectorImpl implements PropertySelector {\r
-\r
-               private Set<String> includeProperties;\r
-               /**\r
-                * \r
-                */\r
-               private static final long serialVersionUID = -3175311800911570546L;\r
-\r
-               public PropertySelectorImpl(Set<String> includeProperties) {\r
-                       this.includeProperties = includeProperties;\r
-               }\r
-\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
+        Criteria criteria = null;\r
+\r
+        if(clazz == null) {\r
+            criteria = getSession().createCriteria(type);\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
+        }\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
+        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
+            return null;\r
+        }\r
+        defaultBeanInitializer.load(bean);\r
+\r
+        return bean;\r
+    }\r
+\r
+    @Override\r
+    public T load(int id, List<String> propertyPaths){\r
+        T bean = findById(id);\r
+        if(bean == null){\r
+            return bean;\r
+        }\r
+        defaultBeanInitializer.initialize(bean, propertyPaths);\r
+\r
+        return bean;\r
+    }\r
+\r
+    @Override\r
+    public T load(UUID uuid, List<String> propertyPaths){\r
+        T bean = findByUuid(uuid);\r
+        if(bean == null){\r
+            return bean;\r
+        }\r
+        defaultBeanInitializer.initialize(bean, propertyPaths);\r
+\r
+        return bean;\r
+    }\r
+\r
+    @Override\r
+    public Boolean exists(UUID uuid) {\r
+        if (findByUuid(uuid)==null){\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+\r
+    @Override\r
+    public int count() {\r
+        return count(type);\r
+    }\r
+\r
+    @Override\r
+    public int count(Class<? extends T> clazz) {\r
+        Session session = getSession();\r
+        Criteria criteria = 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
+    }\r
+\r
+    @Override\r
+    public List<T> list(Integer limit, Integer start) {\r
+        return list(limit, start, null);\r
+    }\r
+\r
+    @Override\r
+    public List<Object[]> group(Class<? extends T> clazz,Integer limit, Integer start, List<Grouping> groups, 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
+\r
+        addGroups(criteria,groups);\r
+\r
+        if(limit != null) {\r
+            criteria.setFirstResult(start);\r
+            criteria.setMaxResults(limit);\r
+        }\r
+\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
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    protected void countGroups(DetachedCriteria criteria,List<Grouping> groups) {\r
+        if(groups != null){\r
+\r
+\r
+            Map<String,String> aliases = new HashMap<String,String>();\r
+\r
+            for(Grouping grouping : groups) {\r
+                if(grouping.getAssociatedObj() != null) {\r
+                    String alias = 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
+                    }\r
+                }\r
+            }\r
+\r
+            ProjectionList projectionList = Projections.projectionList();\r
+\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
+\r
+\r
+            Map<String,String> aliases = new HashMap<String,String>();\r
+\r
+            for(Grouping grouping : groups) {\r
+                if(grouping.getAssociatedObj() != null) {\r
+                    String alias = 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
+                    }\r
+                }\r
+            }\r
+\r
+            ProjectionList projectionList = Projections.projectionList();\r
+\r
+            for(Grouping grouping : groups) {\r
+                grouping.addProjection(projectionList);\r
+            }\r
+            criteria.setProjection(projectionList);\r
+\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
+       int type = SortField.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
+    }\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
+            criteria.setFirstResult(start);\r
+            criteria.setMaxResults(limit);\r
+        }\r
+\r
+        addOrder(criteria,orderHints);\r
+        List<T> results = criteria.list();\r
+\r
+        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
+        return results;\r
+    }\r
+\r
+    @Override\r
+    public List<T> list(Class<? extends T> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+        Criteria criteria = 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
+\r
+        addOrder(criteria,orderHints);\r
+\r
+        List<T> results = criteria.list();\r
+        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
+        return results;\r
+    }\r
+\r
+    public List<T> list(Class<? extends T> type, Integer limit, Integer start, List<OrderHint> orderHints) {\r
+        return list(type,limit,start,orderHints,null);\r
+    }\r
+\r
+    @Override\r
+    public List<T> list(Class<? extends T> 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
+        List<T> result = query.list();\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public Class<T> getType() {\r
+        return type;\r
+    }\r
+\r
+    protected void setPagingParameter(Query query, Integer pageSize, Integer pageNumber){\r
+        if(pageSize != null) {\r
+            query.setMaxResults(pageSize);\r
+            if(pageNumber != null) {\r
+                query.setFirstResult(pageNumber * 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
+            query.setMaxResults(pageSize);\r
+            if(pageNumber != null) {\r
+                query.setFirstResult(pageNumber * pageSize);\r
+            } else {\r
+                query.setFirstResult(0);\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public int count(T example, Set<String> includeProperties) {\r
+        Criteria criteria = getSession().createCriteria(example.getClass());\r
+        addExample(criteria,example,includeProperties);\r
+\r
+        criteria.setProjection(Projections.rowCount());\r
+        return ((Number)criteria.uniqueResult()).intValue();\r
+    }\r
+\r
+    protected void addExample(Criteria criteria, T example, Set<String> includeProperties) {\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
+                    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
+                        } 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
+                    } catch (HibernateException he) {\r
+                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, he);\r
+                    } catch (IllegalArgumentException iae) {\r
+                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, iae);\r
+                    } catch (IllegalAccessException ie) {\r
+                        throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property, ie);\r
+                    }\r
+\r
+                }\r
+            }\r
+        } else {\r
+            criteria.add(Example.create(example));\r
+        }\r
+    }\r
+\r
+\r
+    protected int countByParam(Class<? extends T> clazz, String param, String queryString, MatchMode matchmode, List<Criterion> criterion) {\r
+        Criteria criteria = null;\r
+\r
+        if(clazz == null) {\r
+            criteria = getSession().createCriteria(type);\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
+        }\r
+\r
+        addCriteria(criteria, criterion);\r
+\r
+        criteria.setProjection(Projections.rowCount());\r
+\r
+        List<T> result = criteria.list();\r
+        return ((Number)criteria.uniqueResult()).intValue();\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
+\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
+\r
+        addOrder(criteria,orderHints);\r
+\r
+        List<T> results = criteria.list();\r
+        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
+        return results;\r
+    }\r
+\r
+    private class PropertySelectorImpl implements PropertySelector {\r
+\r
+        private final Set<String> includeProperties;\r
+        /**\r
+         *\r
+         */\r
+        private static final long serialVersionUID = -3175311800911570546L;\r
+\r
+        public PropertySelectorImpl(Set<String> includeProperties) {\r
+            this.includeProperties = includeProperties;\r
+        }\r
+\r
+        @Override\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