TaxonDaoTest is running again
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / taxon / TaxonDaoHibernateImpl.java
index 9e5c2f52afe7379139d17742560c184bb7ebc1c8..e0931da24674081ac49de7018201680d44c6002c 100644 (file)
@@ -9,10 +9,8 @@
 package eu.etaxonomy.cdm.persistence.dao.hibernate.taxon;\r
 \r
 import java.lang.reflect.Field;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.lang.reflect.Method;\r
 import java.util.ArrayList;\r
-import java.util.Collections;\r
+import java.util.Collection;\r
 import java.util.Comparator;\r
 import java.util.HashSet;\r
 import java.util.Iterator;\r
@@ -26,21 +24,15 @@ import org.apache.log4j.Logger;
 import org.apache.lucene.analysis.SimpleAnalyzer;\r
 import org.apache.lucene.queryParser.ParseException;\r
 import org.apache.lucene.queryParser.QueryParser;\r
-import org.apache.lucene.search.Sort;\r
-import org.apache.lucene.search.SortField;\r
 import org.hibernate.Criteria;\r
 import org.hibernate.FetchMode;\r
 import org.hibernate.Hibernate;\r
-import org.hibernate.LazyInitializationException;\r
 import org.hibernate.Query;\r
-import org.hibernate.Transaction;\r
 import org.hibernate.criterion.Criterion;\r
-import org.hibernate.criterion.Order;\r
 import org.hibernate.criterion.Projections;\r
 import org.hibernate.criterion.Restrictions;\r
 import org.hibernate.envers.query.AuditEntity;\r
 import org.hibernate.envers.query.AuditQuery;\r
-import org.hibernate.search.FullTextQuery;\r
 import org.hibernate.search.FullTextSession;\r
 import org.hibernate.search.Search;\r
 import org.hibernate.search.SearchFactory;\r
@@ -55,14 +47,12 @@ import eu.etaxonomy.cdm.model.common.Extension;
 import eu.etaxonomy.cdm.model.common.Marker;\r
 import eu.etaxonomy.cdm.model.common.OriginalSource;\r
 import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
+import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;\r
 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
 import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
 import eu.etaxonomy.cdm.model.media.Rights;\r
-import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
-import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
-import eu.etaxonomy.cdm.model.occurrence.Collection;\r
-import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
 import eu.etaxonomy.cdm.model.reference.ReferenceBase;\r
 import eu.etaxonomy.cdm.model.taxon.Synonym;\r
 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;\r
@@ -72,18 +62,13 @@ import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;\r
 import eu.etaxonomy.cdm.model.view.AuditEvent;\r
-import eu.etaxonomy.cdm.persistence.dao.BeanInitializer;\r
 import eu.etaxonomy.cdm.persistence.dao.QueryParseException;\r
-import eu.etaxonomy.cdm.persistence.dao.common.ISearchableDao;\r
-import eu.etaxonomy.cdm.persistence.dao.common.ITitledDao;\r
 import eu.etaxonomy.cdm.persistence.dao.hibernate.AlternativeSpellingSuggestionParser;\r
-import eu.etaxonomy.cdm.persistence.dao.hibernate.HibernateBeanInitializer;\r
 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;\r
 import eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao;\r
 import eu.etaxonomy.cdm.persistence.fetch.CdmFetch;\r
 import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
 import eu.etaxonomy.cdm.persistence.query.OrderHint;\r
-import eu.etaxonomy.cdm.persistence.query.SelectMode;\r
 \r
 \r
 /**\r
@@ -96,7 +81,6 @@ import eu.etaxonomy.cdm.persistence.query.SelectMode;
 public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implements ITaxonDao {       \r
        private AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser;\r
        \r
-       \r
        @SuppressWarnings("unused")\r
        private static final Logger logger = Logger.getLogger(TaxonDaoHibernateImpl.class);\r
                \r
@@ -112,8 +96,9 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        \r
        @Autowired(required = false)   //TODO switched of because it caused problems when starting CdmApplicationController\r
        public void setAlternativeSpellingSuggestionParser(AlternativeSpellingSuggestionParser<TaxonBase> alternativeSpellingSuggestionParser) {\r
-               this.alternativeSpellingSuggestionParser = alternativeSpellingSuggestionParser;\r
+               this.alternativeSpellingSuggestionParser = alternativeSpellingSuggestionParser; \r
        }\r
+       \r
 \r
        /* (non-Javadoc)\r
         * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)\r
@@ -221,114 +206,166 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                return (List<TaxonBase>)criteria.list();\r
        }\r
 \r
-       public List<TaxonBase> getTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode,\r
+       public List<TaxonBase> getTaxaByName(Class<? extends TaxonBase> clazz, String queryString, MatchMode matchMode,\r
                        Integer pageSize, Integer pageNumber) {\r
                \r
-               return getTaxaByName(queryString, matchMode, selectMode, null, pageSize, pageNumber);\r
+               return getTaxaByName(clazz, queryString, matchMode, null, null, pageSize, pageNumber, null);\r
        }\r
        \r
        public List<TaxonBase> getTaxaByName(String queryString, MatchMode matchMode, \r
                        Boolean accepted, Integer pageSize, Integer pageNumber) {\r
                \r
                if (accepted == true) {\r
-                       return getTaxaByName(queryString, matchMode, SelectMode.TAXA, pageSize, pageNumber);\r
+                       return getTaxaByName(Taxon.class, queryString, matchMode, pageSize, pageNumber);\r
                } else {\r
-                       return getTaxaByName(queryString, matchMode, SelectMode.SYNONYMS, pageSize, pageNumber);\r
+                       return getTaxaByName(Synonym.class, queryString, matchMode, pageSize, pageNumber);\r
                }\r
        }\r
        \r
        \r
-       public List<TaxonBase> getTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode,\r
-                       ReferenceBase sec, Integer pageSize, Integer pageNumber) {\r
+       public List<TaxonBase> getTaxaByName(Class<? extends TaxonBase> clazz, String queryString, MatchMode matchMode,\r
+                       ReferenceBase sec, Set<NamedArea> namedAreas, Integer pageSize, \r
+                       Integer pageNumber, List<String> propertyPaths) {\r
+                               \r
+               \r
+               boolean doCount = false;\r
+               \r
+               Query query = prepareTaxaByName(clazz, queryString, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
 \r
-               Criteria criteria = null;\r
-               Class<?> clazz = selectMode.criteria();\r
-               criteria = getSession().createCriteria(clazz);\r
+               List<TaxonBase> results = query.list();\r
                \r
-               criteria.setFetchMode( "name", FetchMode.JOIN );\r
-               criteria.createAlias("name", "name");\r
+               defaultBeanInitializer.initializeAll(results, propertyPaths);\r
                \r
-               if (queryString != null) {\r
-                       String hqlQueryString = matchMode.queryStringFrom(queryString);\r
-                       if (matchMode == MatchMode.EXACT) {\r
-                               criteria.add(Restrictions.eq("name.nameCache", hqlQueryString));\r
+               return results;\r
+               \r
+       }\r
+\r
+       /**\r
+        * @param clazz\r
+        * @param queryString\r
+        * @param matchMode\r
+        * @param namedAreas\r
+        * @param pageSize\r
+        * @param pageNumber\r
+        * @param doCount\r
+        * @return\r
+        * \r
+        * FIXME implement taxontree restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}\r
+        */\r
+       private Query prepareTaxaByName(Class<? extends TaxonBase> clazz, String queryString, MatchMode matchMode,\r
+                       Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount) {\r
+       \r
+               \r
+               //TODO ? checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec)");\r
+\r
+               String hqlQueryString = matchMode.queryStringFrom(queryString);\r
+               \r
+               String matchOperator;\r
+               if (matchMode == MatchMode.EXACT) {\r
+                       matchOperator = "=";\r
+               } else {\r
+                       matchOperator = "like";\r
+               }\r
+               \r
+               String selectWhat = (doCount ? "count(distinct t)": "distinct t");\r
+               \r
+               String hql = "";\r
+               Set<NamedArea> areasExpanded = new HashSet<NamedArea>();\r
+               if(namedAreas != null && namedAreas.size() > 0){\r
+                       // expand areas\r
+                       List<NamedArea> childAreas;\r
+                       Query areaQuery = getSession().createQuery("select childArea from NamedArea as childArea left join childArea.partOf as parentArea where parentArea = :area");\r
+                       expandNamedAreas(namedAreas, areasExpanded, areaQuery);\r
+                       \r
+                       if(clazz.equals(Taxon.class)){\r
+                               hql = "select " + selectWhat + " from Distribution e join e.inDescription d join d.taxon t join t.name n "+\r
+                                       " where e.area in (:namedAreas) AND n.nameCache " + matchOperator + " :queryString";   \r
                        } else {\r
-                               criteria.add(Restrictions.ilike("name.nameCache", hqlQueryString));\r
+                               //FIXME implement\r
+                               logger.warn("find synonyms by area not jet implemented");\r
+                               hql = "select " + selectWhat + " from Distribution e join e.inDescription d join d.taxon t join t.name n "+\r
+                                       " where e.area in (:namedAreas) AND n.nameCache " + matchOperator + " :queryString";   \r
                        }\r
+               } else {\r
+                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" \r
+                       + " where t.name.nameCache " + matchOperator + " :queryString";\r
                }\r
                \r
-               if (sec != null && sec.getId() != 0) {\r
-                       criteria.add(Restrictions.eq("sec", sec ) );\r
+               if(!doCount){\r
+                       hql += " order by t.titleCache"; //" order by t.name.nameCache";\r
                }\r
                \r
-               criteria.addOrder(Order.asc("name.nameCache"));\r
-                \r
-               if(pageSize != null) {\r
-                       criteria.setMaxResults(pageSize);\r
+               Query query = getSession().createQuery(hql);\r
+               \r
+               query.setParameter("queryString", hqlQueryString);\r
+               if(areasExpanded.size() > 0){\r
+                       query.setParameterList("namedAreas", areasExpanded);\r
+               }\r
+               \r
+               if(pageSize != null &&  !doCount) {\r
+                       query.setMaxResults(pageSize);\r
                        if(pageNumber != null) {\r
-                               criteria.setFirstResult(pageNumber * pageSize);\r
+                               query.setFirstResult(pageNumber * pageSize);\r
                        }\r
                }\r
-\r
-               List<TaxonBase> results = criteria.list();\r
-               return results;\r
-               \r
+               return query;\r
        }\r
        \r
-       public Integer countTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode) {\r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.ReferenceBase, java.util.Set)\r
+        */\r
+       public long countTaxaByName(Class<? extends TaxonBase> clazz, String queryString, MatchMode matchMode,\r
+               ReferenceBase sec, Set<NamedArea> namedAreas) {\r
+               \r
+               boolean doCount = true;\r
+               Query query = prepareTaxaByName(clazz, queryString, matchMode, namedAreas, null, null, doCount);\r
+               Object result = query.uniqueResult();\r
+               return (Long) result;\r
                \r
-               return countTaxaByName(queryString, matchMode, selectMode, null);\r
        }\r
 \r
-       public Integer countTaxaByName(String queryString, \r
-                       MatchMode matchMode, SelectMode selectMode, ReferenceBase sec) {\r
-\r
-               Criteria criteria = null;\r
-               Class<?> clazz = selectMode.criteria();\r
-               criteria = getSession().createCriteria(clazz);\r
-\r
-               criteria.setFetchMode( "name", FetchMode.JOIN );\r
-               criteria.createAlias("name", "name");\r
-\r
-               if (queryString != null) {\r
-                       String hqlQueryString = matchMode.queryStringFrom(queryString);\r
-                       if (matchMode == MatchMode.EXACT) {\r
-                               criteria.add(Restrictions.eq("name.nameCache", hqlQueryString));\r
-                       } else {\r
-                               criteria.add(Restrictions.ilike("name.nameCache", hqlQueryString));\r
+       /**\r
+        * @param namedAreas\r
+        * @param areasExpanded\r
+        * @param areaQuery\r
+        */\r
+       private void expandNamedAreas(Collection<NamedArea> namedAreas, Set<NamedArea> areasExpanded, Query areaQuery) {\r
+               List<NamedArea> childAreas;\r
+               for(NamedArea a : namedAreas){\r
+                       areasExpanded.add(a);\r
+                       areaQuery.setParameter("area", a);\r
+                       childAreas = areaQuery.list();\r
+                       if(childAreas.size() > 0){\r
+                               areasExpanded.addAll(childAreas);\r
+                               expandNamedAreas(childAreas, areasExpanded, areaQuery);\r
                        }\r
                }\r
-\r
-               if (sec != null && sec.getId() != 0) {\r
-                       criteria.add(Restrictions.eq("sec", sec ) );\r
-               }\r
-\r
-               criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
-               return (Integer)criteria.uniqueResult();\r
-\r
        }\r
        \r
-       public Integer countTaxaByName(String queryString, MatchMode matchMode, Boolean accepted) {\r
-               \r
-               Criteria criteria = null;\r
-               if (accepted == true) {\r
-                       criteria = getSession().createCriteria(Taxon.class);\r
-               } else {\r
-                       criteria = getSession().createCriteria(Synonym.class);\r
-               }\r
+//     /* (non-Javadoc)\r
+//      * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode)\r
+//      */\r
+//     public Integer countTaxaByName(String queryString, MatchMode matchMode, SelectMode selectMode) {                \r
+//             return countTaxaByName(queryString, matchMode, selectMode, null);\r
+//     }\r
 \r
-               criteria.setFetchMode( "name", FetchMode.JOIN );\r
-               criteria.createAlias("name", "name");\r
-               \r
-               if (matchMode == MatchMode.EXACT) {\r
-                       criteria.add(Restrictions.eq("name.nameCache", matchMode.queryStringFrom(queryString)));\r
-               } else {\r
-                       criteria.add(Restrictions.ilike("name.nameCache", matchMode.queryStringFrom(queryString)));\r
-               }\r
-               \r
-               criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
-               return (Integer)criteria.uniqueResult();\r
-       }\r
+//     /* (non-Javadoc)\r
+//      * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#countTaxaByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, eu.etaxonomy.cdm.persistence.query.SelectMode, eu.etaxonomy.cdm.model.reference.ReferenceBase)\r
+//      */\r
+//     public Integer countTaxaByName(String queryString, \r
+//                     MatchMode matchMode, SelectMode selectMode, ReferenceBase sec) {\r
+//\r
+//             Long count = countTaxaByName(queryString, matchMode, selectMode, sec, null);\r
+//             return count.intValue();\r
+//\r
+//     }\r
+       \r
+//     public Integer countTaxaByName(String queryString, MatchMode matchMode, Boolean accepted) {\r
+//             \r
+//             SelectMode selectMode = (accepted ? SelectMode.TAXA : SelectMode.SYNONYMS);\r
+//             Long count = countTaxaByName(queryString, matchMode, selectMode, null, null);\r
+//             return count.intValue();\r
+//     }\r
        \r
 \r
        public List<TaxonBase> getAllTaxonBases(Integer pagesize, Integer page) {\r
@@ -533,24 +570,23 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                return result;\r
        }\r
 \r
-       public int countRelatedTaxa(Taxon taxon, TaxonRelationshipType type) {\r
+       public int countTaxonRelationships(Taxon taxon, TaxonRelationshipType type, Direction direction) {\r
                AuditEvent auditEvent = getAuditEventFromContext();\r
                if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {\r
                    Query query = null;\r
                \r
                    if(type == null) {\r
-                           query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship.relatedTo = :relatedTo");\r
+                           query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon");\r
                    } else {\r
-                           query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship.relatedTo = :relatedTo and taxonRelationship.type = :type");\r
+                           query = getSession().createQuery("select count(taxonRelationship) from TaxonRelationship taxonRelationship where taxonRelationship."+direction+" = :relatedTaxon and taxonRelationship.type = :type");\r
                            query.setParameter("type",type);\r
                    }\r
-               \r
-                   query.setParameter("relatedTo", taxon);\r
+                   query.setParameter("relatedTaxon", taxon);\r
                \r
                    return ((Long)query.uniqueResult()).intValue();\r
                } else {\r
                        AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(TaxonRelationship.class,auditEvent.getRevisionNumber());\r
-                       query.add(AuditEntity.relatedId("relatedTo").eq(taxon.getId()));\r
+                       query.add(AuditEntity.relatedId(direction.toString()).eq(taxon.getId()));\r
                        query.addProjection(AuditEntity.id().count("id"));\r
                        \r
                        if(type != null) {\r
@@ -613,34 +649,15 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                }\r
        }\r
        \r
-       public int countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec) {\r
-               checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec)");\r
-               Criteria criteria = null;\r
-               \r
-               if (accepted == true) {\r
-                       criteria = getSession().createCriteria(Taxon.class);\r
-               } else {\r
-                       criteria = getSession().createCriteria(Synonym.class);\r
-               }\r
-               \r
-               criteria.setFetchMode( "name", FetchMode.JOIN );\r
-               criteria.createAlias("name", "name");\r
-\r
-               if (sec != null){\r
-                       if(sec.getId() == 0){\r
-                               getSession().save(sec);\r
-                       }\r
-                       criteria.add(Restrictions.eq("sec", sec ) );\r
-               }\r
-               if (queryString != null) {\r
-                       criteria.add(Restrictions.ilike("name.nameCache", queryString));\r
-               }\r
-               criteria.setProjection(Projections.projectionList().add(Projections.rowCount()));\r
-               \r
-               return (Integer)criteria.uniqueResult();\r
-       }\r
+//     public int countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec) {\r
+//             \r
+//             SelectMode selectMode = (accepted ? SelectMode.TAXA : SelectMode.SYNONYMS);\r
+//             Long count = countTaxaByName(queryString, MatchMode.ANYWHERE, selectMode , sec, null);\r
+//             \r
+//             return count.intValue();\r
+//     }\r
 \r
-       public int countTaxaByName(Class<? extends TaxonBase> clazz, String genusOrUninomial,   String infraGenericEpithet, String specificEpithet,     String infraSpecificEpithet, Rank rank) {\r
+       public int countTaxaByName(Class<? extends TaxonBase> clazz, String genusOrUninomial, String infraGenericEpithet, String specificEpithet,       String infraSpecificEpithet, Rank rank) {\r
                checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(Boolean accepted, String genusOrUninomial,   String infraGenericEpithet, String specificEpithet,     String infraSpecificEpithet, Rank rank)");\r
         Criteria criteria = null;\r
                \r
@@ -732,7 +749,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                return (List<TaxonBase>)criteria.list();\r
        }\r
 \r
-       public List<TaxonRelationship> getRelatedTaxa(Taxon taxon,      TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+       public List<TaxonRelationship> getTaxonRelationships(Taxon taxon,       TaxonRelationshipType type, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths, Direction direction) {\r
                AuditEvent auditEvent = getAuditEventFromContext();\r
                if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {\r
                        Criteria criteria = getSession().createCriteria(TaxonRelationship.class);\r