the query of prepareQuery always returns the type, if doNotReturnFullEntities is set
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / taxon / TaxonDaoHibernateImpl.java
index 200c0bc0b4bc7b4bbeeb6a18c7dd1a132e663ced..fe57c5371d3cc10548ad3adcf34780695efa3719 100644 (file)
@@ -46,16 +46,16 @@ import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.common.LSID;\r
 import eu.etaxonomy.cdm.model.common.OriginalSourceBase;\r
 import eu.etaxonomy.cdm.model.common.RelationshipBase;\r
-import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
 import eu.etaxonomy.cdm.model.common.RelationshipBase.Direction;\r
+import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;\r
 import eu.etaxonomy.cdm.model.location.NamedArea;\r
 import eu.etaxonomy.cdm.model.name.NonViralName;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
 import eu.etaxonomy.cdm.model.name.TaxonNameComparator;\r
 import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;\r
-import eu.etaxonomy.cdm.model.reference.ReferenceFactory;\r
+import eu.etaxonomy.cdm.model.reference.Reference;\r
+import eu.etaxonomy.cdm.model.taxon.Classification;\r
 import eu.etaxonomy.cdm.model.taxon.Synonym;\r
 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;\r
 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;\r
@@ -64,7 +64,6 @@ import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;\r
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;\r
-import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;\r
 import eu.etaxonomy.cdm.model.view.AuditEvent;\r
 import eu.etaxonomy.cdm.persistence.dao.QueryParseException;\r
 import eu.etaxonomy.cdm.persistence.dao.hibernate.AlternativeSpellingSuggestionParser;\r
@@ -106,17 +105,17 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        \r
 \r
        /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference)\r
         */\r
-       public List<Taxon> getRootTaxa(ReferenceBase sec) {\r
+       public List<Taxon> getRootTaxa(Reference sec) {\r
                return getRootTaxa(sec, CdmFetch.FETCH_CHILDTAXA(), true, false);\r
        }\r
                \r
        /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.ReferenceBase, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.name.Rank, eu.etaxonomy.cdm.model.reference.Reference, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)\r
         */\r
-       public List<Taxon> getRootTaxa(Rank rank, ReferenceBase sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications, List<String> propertyPaths) {\r
-               checkNotInPriorView("TaxonDaoHibernateImpl.getRootTaxa(Rank rank, ReferenceBase sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications)");\r
+       public List<Taxon> getRootTaxa(Rank rank, Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications, List<String> propertyPaths) {\r
+               checkNotInPriorView("TaxonDaoHibernateImpl.getRootTaxa(Rank rank, Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications)");\r
                if (onlyWithChildren == null){\r
                        onlyWithChildren = true;\r
                }\r
@@ -175,27 +174,27 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        }\r
 \r
        /* (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.ReferenceBase, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getRootTaxa(eu.etaxonomy.cdm.model.reference.Reference, eu.etaxonomy.cdm.persistence.fetch.CdmFetch, java.lang.Boolean, java.lang.Boolean)\r
         */\r
-       public List<Taxon> getRootTaxa(ReferenceBase sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications) {\r
+       public List<Taxon> getRootTaxa(Reference sec, CdmFetch cdmFetch, Boolean onlyWithChildren, Boolean withMisapplications) {\r
                return getRootTaxa(null, sec, cdmFetch, onlyWithChildren, withMisapplications, null);\r
        }\r
        \r
        /*\r
         * (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.ReferenceBase)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, eu.etaxonomy.cdm.model.reference.Reference)\r
         */\r
-       public List<TaxonBase> getTaxaByName(String queryString, ReferenceBase sec) {\r
+       public List<TaxonBase> getTaxaByName(String queryString, Reference sec) {\r
                \r
                return getTaxaByName(queryString, true, sec);\r
        }\r
 \r
        /*\r
         * (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, java.lang.Boolean, eu.etaxonomy.cdm.model.reference.ReferenceBase)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.String, java.lang.Boolean, eu.etaxonomy.cdm.model.reference.Reference)\r
         */\r
-       public List<TaxonBase> getTaxaByName(String queryString, Boolean accepted, ReferenceBase sec) {\r
-               checkNotInPriorView("TaxonDaoHibernateImpl.getTaxaByName(String name, ReferenceBase sec)");\r
+       public List<TaxonBase> getTaxaByName(String queryString, Boolean accepted, Reference sec) {\r
+               checkNotInPriorView("TaxonDaoHibernateImpl.getTaxaByName(String name, Reference sec)");\r
                \r
         Criteria criteria = null;\r
                if (accepted == true) {\r
@@ -240,35 +239,83 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        \r
        /*\r
         * (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.TaxonomicTree, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)\r
         */\r
-       public List<TaxonBase> getTaxaByName(Class<? extends TaxonBase> clazz, String queryString, TaxonomicTree taxonomicTree,\r
+       public List<TaxonBase> getTaxaByName(Class<? extends TaxonBase> clazz, String queryString, Classification classification,\r
                        MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, \r
                        Integer pageNumber, List<String> propertyPaths) {\r
                                \r
                boolean doCount = false;\r
-               Query query = prepareTaxaByName(clazz, queryString, taxonomicTree, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
+                       \r
+               Query query = prepareTaxaByName(clazz, "nameCache", queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
+               \r
                if (query != null){\r
                        List<TaxonBase> results = query.list();\r
-                       //results.addAll (prepareTaxaByCommonName(queryString, taxonomicTree, matchMode, namedAreas, pageSize, pageNumber, doCount).list());\r
+                       \r
                        defaultBeanInitializer.initializeAll(results, propertyPaths);\r
                        //TaxonComparatorSearch comp = new TaxonComparatorSearch();\r
                        //Collections.sort(results, comp);\r
                        return results;\r
                }\r
+               \r
                return new ArrayList<TaxonBase>();\r
                \r
        }\r
 \r
        /*\r
         * (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByCommonName(java.lang.String, eu.etaxonomy.cdm.model.taxon.TaxonomicTree, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByName(java.lang.Class, java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)\r
         */\r
-       public List<TaxonBase> getTaxaByCommonName(String queryString, TaxonomicTree taxonomicTree,\r
+       //new search for the editor, for performance issues the return values are only uuid and titleCache, to avoid the initialisation of all objects\r
+       @SuppressWarnings("unchecked")\r
+       public List<UuidAndTitleCache<TaxonBase>> getTaxaByNameForEditor(Class<? extends TaxonBase> clazz, String queryString, Classification classification,\r
+                       MatchMode matchMode, Set<NamedArea> namedAreas) {\r
+               long zstVorher;\r
+               long zstNachher;\r
+                               \r
+               boolean doCount = false;\r
+               Query query = prepareTaxaByNameForEditor(clazz, "nameCache", queryString, classification, matchMode, namedAreas, doCount);\r
+               \r
+               \r
+               if (query != null){\r
+                       List<Object[]> results = query.list();\r
+                       \r
+                       List<UuidAndTitleCache<TaxonBase>> resultObjects = new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
+                       Object[] result;\r
+                       for(int i = 0; i<results.size();i++){\r
+                               result = results.get(i);\r
+                               \r
+                               //unterscheiden von taxa und synonymen\r
+                               if (clazz.equals(Taxon.class)){\r
+                                               resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (String)result[1]));\r
+                               }else if (clazz.equals(Synonym.class)){\r
+                                       resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (String)result[1]));\r
+                               } else{\r
+                                       if (result[2].equals("synonym")) {\r
+                                               resultObjects.add( new UuidAndTitleCache(Synonym.class, (UUID) result[0], (String)result[1]));\r
+                                       }\r
+                                       else {\r
+                                               resultObjects.add( new UuidAndTitleCache(Taxon.class, (UUID) result[0], (String)result[1]));\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       return resultObjects;\r
+                       \r
+               }\r
+               return new ArrayList<UuidAndTitleCache<TaxonBase>>();\r
+               \r
+       }\r
+       \r
+       /*\r
+        * (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getTaxaByCommonName(java.lang.String, eu.etaxonomy.cdm.model.taxon.Classification, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.Set, java.lang.Integer, java.lang.Integer, java.util.List)\r
+        */\r
+       public List<TaxonBase> getTaxaByCommonName(String queryString, Classification classification,\r
                        MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, \r
                        Integer pageNumber, List<String> propertyPaths) {\r
                        boolean doCount = false;        \r
-                       Query query = prepareTaxaByCommonName(queryString, taxonomicTree, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
+                       Query query = prepareTaxaByCommonName(queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
                        if (query != null){\r
                                List<TaxonBase> results = query.list();\r
                                defaultBeanInitializer.initializeAll(results, propertyPaths);\r
@@ -278,11 +325,11 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                \r
        }\r
        \r
-\r
        /**\r
         * @param clazz\r
+        * @param searchField the field in TaxonNameBase to be searched through usually either <code>nameCache</code> or <code>titleCache</code>\r
         * @param queryString\r
-        * @param taxonomicTree TODO\r
+        * @param classification TODO\r
         * @param matchMode\r
         * @param namedAreas\r
         * @param pageSize\r
@@ -290,22 +337,298 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
         * @param doCount\r
         * @return\r
         * \r
-        * FIXME implement taxontree restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}\r
+        *\r
         */\r
-       private Query prepareTaxaByName(Class<? extends TaxonBase> clazz, String queryString, TaxonomicTree taxonomicTree,\r
-                       MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount) {\r
-\r
-               //TODO ? checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(String queryString, Boolean accepted, ReferenceBase sec)");\r
-\r
+       private Query prepareTaxaByNameForEditor(Class<? extends TaxonBase> clazz, String searchField, String queryString, Classification classification,\r
+                       MatchMode matchMode, Set<NamedArea> namedAreas, boolean doCount) {\r
+               return prepareQuery(clazz, searchField, queryString, classification,\r
+                               matchMode, namedAreas, doCount, true);\r
+       }\r
+       \r
+       /**\r
+        * @param clazz\r
+        * @param searchField\r
+        * @param queryString\r
+        * @param classification\r
+        * @param matchMode\r
+        * @param namedAreas\r
+        * @param doCount\r
+        * @param doNotReturnFullEntities\r
+        *            if set true the seach method will not return synonym and taxon\r
+        *            entities but an array containing the uuid, titleCache, and the\r
+        *            DTYPE in lowercase letters.\r
+        * @return\r
+        */\r
+       private Query prepareQuery(Class<? extends TaxonBase> clazz, String searchField, String queryString, Classification classification,\r
+                       MatchMode matchMode, Set<NamedArea> namedAreas, boolean doCount, boolean doNotReturnFullEntities){\r
+               \r
                String hqlQueryString = matchMode.queryStringFrom(queryString);\r
+               String selectWhat;\r
+               if (doNotReturnFullEntities){\r
+                       selectWhat = "t.uuid, t.titleCache ";\r
+               }else {\r
+                       selectWhat = (doCount ? "count(t)": "t");\r
+               }\r
+               \r
+               String hql = "";\r
+               Set<NamedArea> areasExpanded = new HashSet<NamedArea>();\r
+               if(namedAreas != null && namedAreas.size() > 0){\r
+                       // expand areas and restrict by distribution area\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
+               boolean doAreaRestriction = areasExpanded.size() > 0;\r
+               \r
+               Set<UUID> namedAreasUuids = new HashSet<UUID>();\r
+               for (NamedArea area:areasExpanded){\r
+                       namedAreasUuids.add(area.getUuid());\r
+               }\r
                \r
-               String matchOperator;\r
-               if (matchMode == MatchMode.EXACT) {\r
-                       matchOperator = "=";\r
+               String taxonSubselect = null;\r
+               String synonymSubselect = null;\r
+               \r
+               if(classification != null){\r
+                       \r
+                       if(doAreaRestriction){\r
+                               \r
+                               taxonSubselect = "select t.id from" +\r
+                                       " Distribution e" +\r
+                                       " join e.inDescription d" +\r
+                                       " join d.taxon t" +\r
+                                       " join t.name n " +\r
+                                       " join t.taxonNodes as tn "+\r
+                                       " where" +\r
+                                       " e.area.uuid in (:namedAreasUuids) AND" +\r
+                                       " tn.classification = :classification" +\r
+                                       " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";\r
+                               \r
+                               \r
+                               synonymSubselect = "select s.id from" +\r
+                                       " Distribution e" +\r
+                                       " join e.inDescription d" +\r
+                                       " join d.taxon t" + // the taxa\r
+                                       " join t.taxonNodes as tn "+\r
+                                       " join t.synonymRelations sr" +\r
+                                       " join sr.relatedFrom s" + // the synonyms\r
+                                       " join s.name sn"+ \r
+                                       " where" +\r
+                                       " e.area.uuid in (:namedAreasUuids) AND" +\r
+                                       " tn.classification = :classification" +\r
+                                       " AND sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                               \r
+                       } else {\r
+                               \r
+                               taxonSubselect = "select t.id from" +\r
+                                       " Taxon t" +\r
+                                       " join t.name n " +\r
+                                       " join t.taxonNodes as tn "+\r
+                                       " where" +\r
+                                       " tn.classification = :classification" +\r
+                                       " AND n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                               \r
+                               synonymSubselect = "select s.id from" +\r
+                                       " Taxon t" + // the taxa\r
+                                       " join t.taxonNodes as tn "+\r
+                                       " join t.synonymRelations sr" +\r
+                                       " join sr.relatedFrom s" + // the synonyms\r
+                                       " join s.name sn"+ \r
+                                       " where" +\r
+                                       " tn.classification = :classification" +\r
+                                       " AND sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                       }       \r
                } else {\r
-                       matchOperator = "like";\r
+                       \r
+                       if(doAreaRestriction){\r
+                               \r
+                               taxonSubselect = "select t.id from " +\r
+                                       " Distribution e" +\r
+                                       " join e.inDescription d" +\r
+                                       " join d.taxon t" +\r
+                                       " join t.name n "+\r
+                                       " where" +\r
+                                       (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +\r
+                                       " n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                               \r
+                               synonymSubselect = "select s.id from" +\r
+                                       " Distribution e" +\r
+                                       " join e.inDescription d" +\r
+                                       " join d.taxon t" + // the taxa\r
+                                       " join t.synonymRelations sr" +\r
+                                       " join sr.relatedFrom s" + // the synonyms\r
+                                       " join s.name sn"+ \r
+                                       " where" +\r
+                                       (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +\r
+                                       " sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                               \r
+                       } else {\r
+                               \r
+                               taxonSubselect = "select t.id from " +\r
+                                       " Taxon t" +\r
+                                       " join t.name n "+\r
+                                       " where" +\r
+                                       " n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+\r
+                               synonymSubselect = "select s.id from" +\r
+                                       " Taxon t" + // the taxa\r
+                                       " join t.synonymRelations sr" +\r
+                                       " join sr.relatedFrom s" + // the synonyms\r
+                                       " join s.name sn"+ \r
+                                       " where" +\r
+                                       " sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
+                       }\r
+                       \r
                }\r
                \r
+               Query subTaxon = null;\r
+               Query subSynonym = null;\r
+               if(clazz.equals(Taxon.class)){\r
+                       // find Taxa\r
+                       subTaxon = getSession().createQuery(taxonSubselect).setParameter("queryString", hqlQueryString);\r
+                       //subTaxon = getSession().createQuery(taxonSubselect);\r
+                       \r
+                       if(doAreaRestriction){\r
+                               subTaxon.setParameterList("namedAreasUuids", namedAreasUuids);\r
+                       }       \r
+                       if(classification != null){\r
+                               subTaxon.setParameter("classification", classification);\r
+                       }\r
+               } else if(clazz.equals(Synonym.class)){\r
+                       // find synonyms\r
+                       subSynonym = getSession().createQuery(synonymSubselect).setParameter("queryString", hqlQueryString);\r
+                       \r
+                       if(doAreaRestriction){\r
+                               subSynonym.setParameterList("namedAreasUuids", namedAreasUuids);\r
+                       }               \r
+                       if(classification != null){\r
+                               subSynonym.setParameter("classification", classification);\r
+                       }\r
+               } else {\r
+                       // find taxa and synonyms\r
+                       subSynonym = getSession().createQuery(synonymSubselect).setParameter("queryString", hqlQueryString);\r
+                       subTaxon = getSession().createQuery(taxonSubselect).setParameter("queryString", hqlQueryString);\r
+                       if(doAreaRestriction){\r
+                               subTaxon.setParameterList("namedAreasUuids", namedAreasUuids);\r
+                               subSynonym.setParameterList("namedAreasUuids", namedAreasUuids);\r
+                       }\r
+                       if(classification != null){\r
+                               subTaxon.setParameter("classification", classification);\r
+                               subSynonym.setParameter("classification", classification);\r
+                       }\r
+               }\r
+               \r
+               List<Integer> taxa = new ArrayList<Integer>();\r
+               List<Integer> synonyms = new ArrayList<Integer>();\r
+               if(clazz.equals(Taxon.class)){\r
+                       taxa = subTaxon.list();\r
+                       \r
+               }else if (clazz.equals(Synonym.class)){\r
+                       synonyms = subSynonym.list();\r
+               }else {\r
+                       taxa = subTaxon.list();\r
+                       synonyms = subSynonym.list();\r
+               }\r
+               if(clazz.equals(Taxon.class)){\r
+                       if  (taxa.size()>0){\r
+                               if (doNotReturnFullEntities){\r
+                                       hql = "select " + selectWhat + ", 'taxon' from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa)";\r
+                               }else{\r
+                                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa)";\r
+                               }\r
+                       }else{\r
+                               hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t";\r
+                       }\r
+               } else if(clazz.equals(Synonym.class) ){\r
+                       if (synonyms.size()>0){\r
+                               if (doNotReturnFullEntities){\r
+                                       hql = "select " + selectWhat + ", 'synonym' from " + clazz.getSimpleName() + " t" + " where t.id in (:synonyms)";\r
+                               }else{\r
+                                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" + " where t.id in (:synonyms)";          \r
+                               }\r
+                       }else{\r
+                               hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t";\r
+                       }\r
+               } else {\r
+                       \r
+                       if(synonyms.size()>0 && taxa.size()>0){\r
+                               if (doNotReturnFullEntities &&  !doCount ){\r
+                                       // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:\r
+                                       hql = "select " + selectWhat + ", case when t.id in (:taxa) then 'taxon' else 'synonym' end" + " from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa) OR t.id in (:synonyms)";\r
+                               }else{\r
+                                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa) OR t.id in (:synonyms)";\r
+                               }\r
+                       }else if (synonyms.size()>0 ){\r
+                               if (doNotReturnFullEntities &&  !doCount ){\r
+                                       // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:\r
+                                       hql = "select " + selectWhat + ", 'synonym' from " + clazz.getSimpleName() + " t" + " where t.id in (:synonyms)";       \r
+                               } else {\r
+                                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" + " where t.id in (:synonyms)";          \r
+                               }\r
+                       } else if (taxa.size()>0 ){\r
+                               if (doNotReturnFullEntities &&  !doCount ){\r
+                                       // in doNotReturnFullEntities mode it is nesscary to also return the type of the matching entities:\r
+                                       hql = "select " + selectWhat + ", 'taxon' from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa) ";\r
+                               } else {\r
+                                       hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t" + " where t.id in (:taxa) ";\r
+                               }\r
+                       } else{\r
+                               hql = "select " + selectWhat + " from " + clazz.getSimpleName() + " t";\r
+                       }\r
+               }\r
+               \r
+               if (hql == "") return null;\r
+               if(!doCount){\r
+                       hql += " order by t.name.genusOrUninomial, case when t.name.specificEpithet like '\"%\"' then 1 else 0 end, t.name.specificEpithet, t.name.rank desc, t.name.nameCache";\r
+               }\r
+       \r
+               Query query = getSession().createQuery(hql);\r
+                               \r
+               if(clazz.equals(Taxon.class) && taxa.size()>0){\r
+                       //find taxa\r
+                       query.setParameterList("taxa", taxa );\r
+               } else if(clazz.equals(Synonym.class) && synonyms.size()>0){\r
+                       // find synonyms\r
+                       query.setParameterList("synonyms", synonyms);\r
+                       \r
+               \r
+               } else {\r
+                       // find taxa and synonyms\r
+                       if (taxa.size()>0){\r
+                               query.setParameterList("taxa", taxa);\r
+                       }\r
+                       if (synonyms.size()>0){\r
+                               query.setParameterList("synonyms",synonyms);\r
+                       }\r
+                       if (taxa.size()== 0 && synonyms.size() == 0){\r
+                               return null;\r
+                       }\r
+               }\r
+               return query;\r
+               \r
+       }\r
+       \r
+       \r
+       /**\r
+        * @param clazz\r
+        * @param searchField the field in TaxonNameBase to be searched through usually either <code>nameCache</code> or <code>titleCache</code>\r
+        * @param queryString\r
+        * @param classification TODO\r
+        * @param matchMode\r
+        * @param namedAreas\r
+        * @param pageSize\r
+        * @param pageNumber\r
+        * @param doCount\r
+        * @return\r
+        * \r
+        * FIXME implement classification restriction & implement test: see {@link TaxonDaoHibernateImplTest#testCountTaxaByName()}\r
+        */\r
+       private Query prepareTaxaByName(Class<? extends TaxonBase> clazz, String searchField, String queryString, Classification classification,\r
+                       MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount) {\r
+\r
+               //TODO ? checkNotInPriorView("TaxonDaoHibernateImpl.countTaxaByName(String queryString, Boolean accepted, Reference sec)");\r
+\r
+               /*String hqlQueryString = matchMode.queryStringFrom(queryString);\r
+               \r
                String selectWhat = (doCount ? "count(t)": "t");\r
                \r
                String hql = "";\r
@@ -326,7 +649,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                String taxonSubselect = null;\r
                String synonymSubselect = null;\r
                \r
-               if(taxonomicTree != null){\r
+               if(classification != null){\r
                        \r
                        if(doAreaRestriction){\r
                                \r
@@ -338,8 +661,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join t.taxonNodes as tn "+\r
                                        " where" +\r
                                        " e.area.uuid in (:namedAreasUuids) AND" +\r
-                                       " tn.taxonomicTree = :taxonomicTree" +\r
-                                       " AND n.nameCache " + matchOperator + " :queryString";\r
+                                       " tn.classification = :classification" +\r
+                                       " AND n." + searchField + " " + matchMode.getMatchOperator() + " :queryString";\r
                                \r
                                \r
                                synonymSubselect = "select s.id from" +\r
@@ -352,8 +675,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join s.name sn"+ \r
                                        " where" +\r
                                        " e.area.uuid in (:namedAreasUuids) AND" +\r
-                                       " tn.taxonomicTree = :taxonomicTree" +\r
-                                       " AND sn.nameCache " + matchOperator + " :queryString";\r
+                                       " tn.classification = :classification" +\r
+                                       " AND sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                                \r
                        } else {\r
                                \r
@@ -362,8 +685,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join t.name n " +\r
                                        " join t.taxonNodes as tn "+\r
                                        " where" +\r
-                                       " tn.taxonomicTree = :taxonomicTree" +\r
-                                       " AND n.nameCache " + matchOperator + " :queryString";\r
+                                       " tn.classification = :classification" +\r
+                                       " AND n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                                \r
                                synonymSubselect = "select s.id from" +\r
                                        " Taxon t" + // the taxa\r
@@ -372,8 +695,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join sr.relatedFrom s" + // the synonyms\r
                                        " join s.name sn"+ \r
                                        " where" +\r
-                                       " tn.taxonomicTree = :taxonomicTree" +\r
-                                       " AND sn.nameCache " + matchOperator + " :queryString";\r
+                                       " tn.classification = :classification" +\r
+                                       " AND sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                        }       \r
                } else {\r
                        \r
@@ -386,7 +709,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join t.name n "+\r
                                        " where" +\r
                                        (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +\r
-                                       " n.nameCache " + matchOperator + " :queryString";\r
+                                       " n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                                \r
                                synonymSubselect = "select s.id from" +\r
                                        " Distribution e" +\r
@@ -397,7 +720,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join s.name sn"+ \r
                                        " where" +\r
                                        (doAreaRestriction ? " e.area.uuid in (:namedAreasUuids) AND" : "") +\r
-                                       " sn.nameCache " + matchOperator + " :queryString";\r
+                                       " sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                                \r
                        } else {\r
                                \r
@@ -405,7 +728,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " Taxon t" +\r
                                        " join t.name n "+\r
                                        " where" +\r
-                                       " n.nameCache " + matchOperator + " :queryString";\r
+                                       " n." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
 \r
                                synonymSubselect = "select s.id from" +\r
                                        " Taxon t" + // the taxa\r
@@ -413,7 +736,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                        " join sr.relatedFrom s" + // the synonyms\r
                                        " join s.name sn"+ \r
                                        " where" +\r
-                                       " sn.nameCache " + matchOperator + " :queryString";\r
+                                       " sn." + searchField +  " " + matchMode.getMatchOperator() + " :queryString";\r
                        }\r
                        \r
                \r
@@ -421,7 +744,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                \r
                \r
                \r
-               // TODO  mysql needs  optimization:  see http://www.xaprb.com/blog/2006/04/30/how-to-optimize-subqueries-and-joins-in-mysql/#commen\r
+               \r
                Query subTaxon = null;\r
                Query subSynonym = null;\r
                if(clazz.equals(Taxon.class)){\r
@@ -432,8 +755,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                        if(doAreaRestriction){\r
                                subTaxon.setParameterList("namedAreasUuids", namedAreasUuids);\r
                        }       \r
-                       if(taxonomicTree != null){\r
-                               subTaxon.setParameter("taxonomicTree", taxonomicTree);\r
+                       if(classification != null){\r
+                               subTaxon.setParameter("classification", classification);\r
                        }\r
                } else if(clazz.equals(Synonym.class)){\r
                        // find synonyms\r
@@ -442,8 +765,8 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                        if(doAreaRestriction){\r
                                subSynonym.setParameterList("namedAreasUuids", namedAreasUuids);\r
                        }               \r
-                       if(taxonomicTree != null){\r
-                               subSynonym.setParameter("taxonomicTree", taxonomicTree);\r
+                       if(classification != null){\r
+                               subSynonym.setParameter("classification", classification);\r
                        }\r
                } else {\r
                        // find taxa and synonyms\r
@@ -453,9 +776,9 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                subTaxon.setParameterList("namedAreasUuids", namedAreasUuids);\r
                                subSynonym.setParameterList("namedAreasUuids", namedAreasUuids);\r
                        }\r
-                       if(taxonomicTree != null){\r
-                               subTaxon.setParameter("taxonomicTree", taxonomicTree);\r
-                               subSynonym.setParameter("taxonomicTree", taxonomicTree);\r
+                       if(classification != null){\r
+                               subTaxon.setParameter("classification", classification);\r
+                               subSynonym.setParameter("classification", classification);\r
                        }\r
                }\r
                \r
@@ -524,8 +847,9 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                        if (taxa.size()== 0 && synonyms.size() == 0){\r
                                return null;\r
                        }\r
-               }\r
-               \r
+               }*/\r
+               Query query = prepareQuery(clazz, searchField, queryString, classification,\r
+                               matchMode, namedAreas, doCount, false);\r
                \r
                if(pageSize != null &&  !doCount) {\r
                        query.setMaxResults(pageSize);\r
@@ -537,21 +861,14 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                return query;\r
        }\r
 \r
-       private Query prepareTaxaByCommonName(String queryString, TaxonomicTree taxonomicTree,\r
+       private Query prepareTaxaByCommonName(String queryString, Classification classification,\r
                        MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber, boolean doCount){\r
-               \r
-               String matchOperator;\r
-               if (matchMode == MatchMode.EXACT) {\r
-                       matchOperator = "=";\r
-               } else {\r
-                       matchOperator = "like";\r
-               }\r
-               \r
+                               \r
                String hql= "from Taxon t " +\r
                "join t.descriptions d "+\r
                "join d.descriptionElements e " +\r
                "join e.feature f " +\r
-               "where f.supportsCommonTaxonName = true and e.name "+matchOperator+" :queryString";//and ls.text like 'common%'";\r
+               "where f.supportsCommonTaxonName = true and e.name "+matchMode.getMatchOperator()+" :queryString";//and ls.text like 'common%'";\r
                \r
                Query query = getSession().createQuery(hql);\r
                \r
@@ -567,18 +884,18 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        }\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, java.util.Set)\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.Reference, java.util.Set)\r
         */\r
-       public long countTaxaByName(Class<? extends TaxonBase> clazz, String queryString, TaxonomicTree taxonomicTree,\r
+       public long countTaxaByName(Class<? extends TaxonBase> clazz, String queryString, Classification classification,\r
                MatchMode matchMode, Set<NamedArea> namedAreas) {\r
                \r
                boolean doCount = true;\r
-               Query query = prepareTaxaByName(clazz, queryString, taxonomicTree, matchMode, namedAreas, null, null, doCount);\r
+               Query query = prepareTaxaByName(clazz, "nameCache", queryString, classification, matchMode, namedAreas, null, null, doCount);\r
                if (query != null) {\r
                        return (Long)query.uniqueResult();\r
+               }else{\r
+                       return 0;\r
                }\r
-               return 0;\r
-               \r
        }\r
 \r
        /**\r
@@ -607,10 +924,10 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
 //     }\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
+//      * @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.Reference)\r
 //      */\r
 //     public Integer countTaxaByName(String queryString, \r
-//                     MatchMode matchMode, SelectMode selectMode, ReferenceBase sec) {\r
+//                     MatchMode matchMode, SelectMode selectMode, Reference sec) {\r
 //\r
 //             Long count = countTaxaByName(queryString, matchMode, selectMode, sec, null);\r
 //             return count.intValue();\r
@@ -729,11 +1046,19 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        }\r
 \r
 \r
-       // TODO add generic return type !!\r
-       public List findByName(String queryString, MatchMode matchMode, int page, int pagesize, boolean onlyAcccepted) {\r
-               ArrayList<Criterion> criteria = new ArrayList<Criterion>();\r
-               //TODO ... Restrictions.eq(propertyName, value)\r
-               return super.findByTitle(queryString, matchMode, page, pagesize, criteria);\r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#findByName(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, int, int, boolean)\r
+        */\r
+       public List<TaxonBase> findByNameTitleCache(Class<? extends TaxonBase>clazz, String queryString, Classification classification, MatchMode matchMode, Set<NamedArea> namedAreas, Integer pageNumber, Integer pageSize, List<String> propertyPaths) {\r
+       \r
+               boolean doCount = false;\r
+               Query query = prepareTaxaByName(clazz, "titleCache", queryString, classification, matchMode, namedAreas, pageSize, pageNumber, doCount);\r
+               if (query != null){\r
+                       List<TaxonBase> results = query.list();\r
+                       defaultBeanInitializer.initializeAll(results, propertyPaths);\r
+                       return results;\r
+               }\r
+               return new ArrayList<TaxonBase>();\r
 \r
        }\r
 \r
@@ -1183,13 +1508,13 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        \r
        /*\r
         * (non-Javadoc)\r
-        * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheOfAcceptedTaxa(eu.etaxonomy.cdm.model.taxon.TaxonomicTree)\r
+        * @see eu.etaxonomy.cdm.api.service.ITaxonService#getUuidAndTitleCacheOfAcceptedTaxa(eu.etaxonomy.cdm.model.taxon.Classification)\r
         */\r
-       public List<UuidAndTitleCache<TaxonNode>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByTaxonomicTree(TaxonomicTree taxonomicTree) {\r
+       public List<UuidAndTitleCache<TaxonNode>> getTaxonNodeUuidAndTitleCacheOfAcceptedTaxaByClassification(Classification classification) {\r
 \r
-               int taxonomicTreeId = taxonomicTree.getId();\r
+               int classificationId = classification.getId();\r
                \r
-               String queryString = "SELECT nodes.uuid, taxa.titleCache FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.taxonomictree_id = " + taxonomicTreeId;\r
+               String queryString = "SELECT nodes.uuid, taxa.titleCache FROM TaxonNode AS nodes LEFT JOIN TaxonBase AS taxa ON nodes.taxon_id = taxa.id WHERE taxa.DTYPE = 'Taxon' AND nodes.classification_id = " + classificationId;\r
                \r
                List<Object[]> result = getSession().createSQLQuery(queryString).list();\r
                                \r
@@ -1266,14 +1591,14 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        }\r
 \r
        public List<TaxonBase> getTaxaByCommonName(String queryString,\r
-                       TaxonomicTree taxonomicTree, MatchMode matchMode,\r
+                       Classification classification, MatchMode matchMode,\r
                        Set<NamedArea> namedAreas, Integer pageSize, Integer pageNumber) {\r
                // TODO Auto-generated method stub\r
                return null;\r
        }\r
        \r
        \r
-       public List<Synonym>  createAllInferredSynonyms(Taxon taxon, TaxonomicTree tree){\r
+       public List<Synonym>  createAllInferredSynonyms(Taxon taxon, Classification tree){\r
                List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
                \r
                inferredSynonyms.addAll(createInferredSynonyms(taxon, tree, SynonymRelationshipType.INFERRED_EPITHET_OF()));\r
@@ -1299,7 +1624,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                return taxonName;\r
        }\r
 \r
-       public List<Synonym> createInferredSynonyms(Taxon taxon, TaxonomicTree tree, SynonymRelationshipType type){\r
+       public List<Synonym> createInferredSynonyms(Taxon taxon, Classification tree, SynonymRelationshipType type){\r
                List <Synonym> inferredSynonyms = new ArrayList<Synonym>();\r
                List<Synonym> inferredSynonymsToBeRemoved = new ArrayList<Synonym>();\r
 \r
@@ -1314,10 +1639,10 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                List<String> taxonNames = new ArrayList<String>();\r
                \r
                for (TaxonNode node: nodes){\r
-                       HashMap<String, String> synonymsGenus = new HashMap<String, String>();\r
+                       HashMap<String, String> synonymsGenus = new HashMap<String, String>(); // Changed this to be able to store the idInSource to a genusName\r
                        List<String> synonymsEpithet = new ArrayList<String>();\r
                        \r
-                       if (node.getTaxonomicTree().equals(tree)){\r
+                       if (node.getClassification().equals(tree)){\r
                                if (!node.isTopmostNode()){\r
                                TaxonNode parent = (TaxonNode)node.getParent();\r
                                parent = (TaxonNode)HibernateProxyHelper.deproxy(parent);\r
@@ -1351,23 +1676,35 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        // Determine the idInSource\r
                                                        String idInSource = getIdInSource(syn);\r
                                                        \r
+                                                       // Determine the sourceReference\r
+                                                       Reference sourceReference = syn.getSec();\r
+                                                       \r
                                                        synName = syn.getName();\r
                                                        ZoologicalName zooName = getZoologicalName(synName.getUuid(), zooHashMap);\r
                                                        String synGenusName = zooName.getGenusOrUninomial();\r
-                                                       if (!synonymsGenus.containsKey(synGenusName)){\r
+                                                       if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){\r
                                                                synonymsGenus.put(synGenusName, idInSource);\r
                                                        }\r
                                                        inferredSynName = ZoologicalName.NewInstance(Rank.SPECIES());\r
+                                                       \r
+                                                       // DEBUG\r
+                                                       if (epithetOfTaxon == null) {\r
+                                                               logger.error("This specificEpithet is NULL");\r
+                                                       }\r
+                                                       \r
                                                        inferredSynName.setSpecificEpithet(epithetOfTaxon);\r
                                                        inferredSynName.setGenusOrUninomial(synGenusName);\r
                                                        inferredEpithet = Synonym.NewInstance(inferredSynName, null);\r
+                                                       \r
+                                                       // Set the sourceReference\r
+                                                       inferredEpithet.setSec(sourceReference);\r
 \r
                                                        // Add the original source\r
                                                        if (idInSource != null) {\r
                                                                IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredEpithetOf", syn.getSec(), null);\r
                                                                \r
                                                                // Add the citation\r
-                                                               ReferenceBase citation = getCitation(syn);\r
+                                                               Reference citation = getCitation(syn);\r
                                                                if (citation != null) {\r
                                                                        originalSource.setCitation(citation);\r
                                                                        inferredEpithet.addSource(originalSource);\r
@@ -1377,7 +1714,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        taxon.addSynonym(inferredEpithet, SynonymRelationshipType.INFERRED_GENUS_OF());\r
                                                        inferredSynonyms.add(inferredEpithet);\r
                                                        inferredSynName.generateTitle();\r
-                                                       zooHashMap.put(inferredSynName.getUuid(), inferredSynName); // I guess this needs to be added here?\r
+                                                       zooHashMap.put(inferredSynName.getUuid(), inferredSynName);\r
                                                        taxonNames.add(inferredSynName.getNameCache());\r
                                                }\r
                                                \r
@@ -1414,11 +1751,14 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        \r
                                                        // Determine the idInSource\r
                                                        String idInSource = getIdInSource(syn);\r
+                                                       \r
+                                                       // Determine the sourceReference\r
+                                                       Reference sourceReference = syn.getSec();\r
 \r
                                                        synName = syn.getName();\r
                                                        ZoologicalName zooName = getZoologicalName(synName.getUuid(), zooHashMap);\r
                                                        String speciesEpithetName = zooName.getSpecificEpithet();\r
-                                                       if (!synonymsEpithet.contains(speciesEpithetName)){\r
+                                                       if (synonymsEpithet != null && !synonymsEpithet.contains(speciesEpithetName)){\r
                                                                synonymsEpithet.add(speciesEpithetName);\r
                                                        }\r
                                                        inferredSynName = ZoologicalName.NewInstance(Rank.SPECIES());\r
@@ -1426,12 +1766,15 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        inferredSynName.setGenusOrUninomial(genusOfTaxon);\r
                                                        inferredGenus = Synonym.NewInstance(inferredSynName, null);\r
                                                        \r
+                                                       // Set the sourceReference\r
+                                                       inferredGenus.setSec(sourceReference);\r
+                                                       \r
                                                        // Add the original source\r
                                                        if (idInSource != null) {\r
                                                                IdentifiableSource originalSource = IdentifiableSource.NewInstance(idInSource, "InferredGenusOf", syn.getSec(), null);\r
                                                                \r
                                                                // Add the citation\r
-                                                               ReferenceBase citation = getCitation(syn);\r
+                                                               Reference citation = getCitation(syn);\r
                                                                if (citation != null) {\r
                                                                        originalSource.setCitation(citation);\r
                                                                        inferredGenus.addSource(originalSource);\r
@@ -1441,7 +1784,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        taxon.addSynonym(inferredGenus, SynonymRelationshipType.INFERRED_EPITHET_OF());\r
                                                        inferredSynonyms.add(inferredGenus);\r
                                                        inferredSynName.generateTitle();\r
-                                                       zooHashMap.put(inferredSynName.getUuid(), inferredSynName); // I guess this needs to be added here?\r
+                                                       zooHashMap.put(inferredSynName.getUuid(), inferredSynName);\r
                                                        taxonNames.add(inferredSynName.getNameCache());\r
                                                }\r
                                                \r
@@ -1467,7 +1810,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                \r
                                        }else if (type.equals(SynonymRelationshipType.POTENTIAL_COMBINATION_OF())){\r
                                                \r
-                                               ReferenceBase sourceReference = null; // TODO: Determination of sourceReference is redundant\r
+                                               Reference sourceReference = null; // TODO: Determination of sourceReference is redundant\r
                                                \r
                                                for (SynonymRelationship synonymRelationOfGenus:synonymRelationshipsOfGenus){\r
                                                        TaxonNameBase synName;\r
@@ -1484,7 +1827,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
 \r
                                                        ZoologicalName zooName = getZoologicalName(synName.getUuid(), zooHashMap);\r
                                                        String synGenusName = zooName.getGenusOrUninomial();\r
-                                                       if (!synonymsGenus.containsKey(synGenusName)){\r
+                                                       if (synGenusName != null && !synonymsGenus.containsKey(synGenusName)){\r
                                                                synonymsGenus.put(synGenusName, idInSource);\r
                                                        }\r
                                                }\r
@@ -1500,7 +1843,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                        \r
                                                        ZoologicalName zooName = getZoologicalName(syn.getName().getUuid(), zooHashMap);\r
                                                        String epithetName = zooName.getSpecificEpithet();\r
-                                                       if (!synonymsEpithet.contains(epithetName)){\r
+                                                       if (epithetName != null && !synonymsEpithet.contains(epithetName)){\r
                                                                synonymsEpithet.add(epithetName);\r
                                                        }\r
                                                }\r
@@ -1511,6 +1854,9 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                                                inferredSynName.setGenusOrUninomial(genusName);\r
                                                                potentialCombination = Synonym.NewInstance(inferredSynName, null);\r
                                                                \r
+                                                               // Set the sourceReference\r
+                                                               potentialCombination.setSec(sourceReference);\r
+                                                               \r
                                                                // Add the original source\r
                                                                String idInSource = synonymsGenus.get(genusName);\r
                                                                if (idInSource != null) {\r
@@ -1595,11 +1941,11 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        }\r
        \r
        /**\r
-        * Returns the idInSource for a given Synonym.\r
+        * Returns the citation for a given Synonym.\r
         * @param syn\r
         */\r
-       private ReferenceBase getCitation(Synonym syn) {\r
-               ReferenceBase citation = null;\r
+       private Reference getCitation(Synonym syn) {\r
+               Reference citation = null;\r
                Set<IdentifiableSource> sources = syn.getSources();\r
                if (sources.size() == 1) {\r
                        IdentifiableSource source = sources.iterator().next();\r
@@ -1696,29 +2042,21 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        //TODO: mal nur mit UUID probieren (ohne fetch all properties), vielleicht geht das schneller?\r
        public List<UUID> findIdenticalTaxonNameIds(List<String> propertyPaths){\r
                Query query=getSession().createQuery("select tmb2 from ZoologicalName tmb, ZoologicalName tmb2 fetch all properties where tmb.id != tmb2.id and tmb.nameCache = tmb2.nameCache");\r
-               System.err.println("query: " + query.getQueryString());\r
                List<UUID> zooNames = query.list();\r
-               System.err.println("number of identical names"+zooNames.size());\r
-               \r
-                                               \r
+                                                               \r
                return zooNames;\r
                \r
        }\r
        \r
        public List<TaxonNameBase> findIdenticalTaxonNames(List<String> propertyPaths) {\r
                \r
-               //hole alle TaxonNames, die es mindestens zweimal gibt.\r
-               \r
-               \r
-               \r
                Query query=getSession().createQuery("select tmb2 from ZoologicalName tmb, ZoologicalName tmb2 fetch all properties where tmb.id != tmb2.id and tmb.nameCache = tmb2.nameCache");\r
-               System.err.println("query: " + query.getQueryString());\r
+               \r
                List<TaxonNameBase> zooNames = query.list();\r
-               System.err.println("number of identical names"+zooNames.size());\r
                \r
                TaxonNameComparator taxComp = new TaxonNameComparator();\r
                Collections.sort(zooNames, taxComp);\r
-               System.err.println("list is sorted");\r
+               \r
                for (TaxonNameBase taxonNameBase: zooNames){\r
                        defaultBeanInitializer.initialize(taxonNameBase, propertyPaths);\r
                }\r
@@ -1729,9 +2067,9 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
        public List<TaxonNameBase> findIdenticalNamesNew(List<String> propertyPaths){\r
                \r
                //Hole die beiden Source_ids von "Fauna Europaea" und "Erms" und in sources der names darf jeweils nur das entgegengesetzte auftreten (i member of tmb.taxonBases)\r
-               Query query = getSession().createQuery("Select id from ReferenceBase where titleCache like 'Fauna Europaea database'");\r
+               Query query = getSession().createQuery("Select id from Reference where titleCache like 'Fauna Europaea database'");\r
                List<String> secRefFauna = query.list();\r
-               query = getSession().createQuery("Select id from ReferenceBase where titleCache like 'ERMS'");\r
+               query = getSession().createQuery("Select id from Reference where titleCache like 'ERMS'");\r
                List<String> secRefErms = query.list();\r
                //Query query = getSession().createQuery("select tmb2.nameCache from ZoologicalName tmb, TaxonBase tb1, ZoologicalName tmb2, TaxonBase tb2 where tmb.id != tmb2.id and tb1.name = tmb and tb2.name = tmb2 and tmb.nameCache = tmb2.nameCache and tb1.sec != tb2.sec");\r
                //Get all names of fauna europaea\r
@@ -1757,7 +2095,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                                identicalNames.add(nameFauna);\r
                        }\r
                }\r
-               System.err.println("number of identical names: " + identicalNames.size());\r
+               \r
                \r
                query = getSession().createQuery("from ZoologicalName zn where zn.nameCache IN (:identicalNames)");\r
                query.setParameterList("identicalNames", identicalNames);\r
@@ -1765,11 +2103,7 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
                TaxonNameBase temp = result.get(0);\r
                \r
                Iterator<OriginalSourceBase> sources = temp.getSources().iterator();\r
-               System.err.println(temp.getSources().size());\r
-               if (sources.hasNext()){\r
-                       System.err.println("funktioniert..."+ sources.next().getIdInSource());\r
-                       //sources.next().getIdInSource();\r
-               }\r
+                               \r
                TaxonNameComparator taxComp = new TaxonNameComparator();\r
                Collections.sort(result, taxComp);\r
                defaultBeanInitializer.initializeAll(result, propertyPaths);\r
@@ -1794,10 +2128,10 @@ public class TaxonDaoHibernateImpl extends IdentifiableDaoBase<TaxonBase> implem
 \r
 \r
        public long countTaxaByCommonName(String searchString,\r
-                       TaxonomicTree taxonomicTree, MatchMode matchMode,\r
+                       Classification classification, MatchMode matchMode,\r
                        Set<NamedArea> namedAreas) {\r
                boolean doCount = true;\r
-               Query query = prepareTaxaByCommonName(searchString, taxonomicTree, matchMode, namedAreas, null, null, doCount);\r
+               Query query = prepareTaxaByCommonName(searchString, classification, matchMode, namedAreas, null, null, doCount);\r
                if (query != null && !query.list().isEmpty()) {\r
                        Object o = query.uniqueResult();\r
                        if(o != null) {\r
@@ -1930,6 +2264,34 @@ WHERE     (FaEuSyn.OriginalDB = N'FaEu') AND (ERMSAcc.OriginalDB = N'ERMS') AND
        }\r
 \r
 \r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getUuidAndTitleCacheTaxon()\r
+        */\r
+       @Override\r
+       public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheTaxon() {\r
+               String queryString = String.format("select uuid, titleCache from %s where DTYPE = '%s'", type.getSimpleName(), Taxon.class.getSimpleName());\r
+               Query query = getSession().createQuery(queryString);\r
+               \r
+               List<UuidAndTitleCache<TaxonBase>> result = getUuidAndTitleCache(query);\r
+               \r
+               return result;\r
+       }\r
+\r
+\r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.persistence.dao.taxon.ITaxonDao#getUuidAndTitleCacheSynonym()\r
+        */\r
+       @Override\r
+       public List<UuidAndTitleCache<TaxonBase>> getUuidAndTitleCacheSynonym() {\r
+               String queryString = String.format("select uuid, titleCache from %s where DTYPE = '%s'", type.getSimpleName(), Synonym.class.getSimpleName());\r
+               Query query = getSession().createQuery(queryString);\r
+               \r
+               List<UuidAndTitleCache<TaxonBase>> result = getUuidAndTitleCache(query);\r
+               \r
+               return result;\r
+       }\r
+\r
+\r
 \r
 \r
        \r