fix #825 rename method that searches by representation label in term dao
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / term / DefinedTermDaoImpl.java
index 69e6ef9b00f48fbf63d058fb97dafbfe3dc763aa..aed1a1d23f88f696ffbd1d541d6a020ba4ad44c7 100644 (file)
@@ -6,19 +6,18 @@
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * See LICENSE.TXT at the top of this package for the full license terms.
 */
-
 package eu.etaxonomy.cdm.persistence.dao.hibernate.term;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Collectors;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
@@ -34,12 +33,12 @@ import org.hibernate.envers.query.AuditEntity;
 import org.hibernate.envers.query.AuditQuery;
 import org.springframework.stereotype.Repository;
 
+import eu.etaxonomy.cdm.common.URI;
 import eu.etaxonomy.cdm.model.common.AnnotationType;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.ExtensionType;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.MarkerType;
-import eu.etaxonomy.cdm.model.description.Feature;
 import eu.etaxonomy.cdm.model.description.MeasurementUnit;
 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
 import eu.etaxonomy.cdm.model.description.State;
@@ -52,7 +51,7 @@ import eu.etaxonomy.cdm.model.location.NamedAreaType;
 import eu.etaxonomy.cdm.model.location.ReferenceSystem;
 import eu.etaxonomy.cdm.model.media.Media;
 import eu.etaxonomy.cdm.model.media.RightsType;
-import eu.etaxonomy.cdm.model.metadata.NamedAreaSearchField;
+import eu.etaxonomy.cdm.model.metadata.TermSearchField;
 import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
 import eu.etaxonomy.cdm.model.name.NameTypeDesignationStatus;
@@ -69,21 +68,24 @@ import eu.etaxonomy.cdm.model.term.TermVocabulary;
 import eu.etaxonomy.cdm.model.view.AuditEvent;
 import eu.etaxonomy.cdm.persistence.dao.hibernate.common.IdentifiableDaoBase;
 import eu.etaxonomy.cdm.persistence.dao.term.IDefinedTermDao;
+import eu.etaxonomy.cdm.persistence.dto.FeatureDto;
 import eu.etaxonomy.cdm.persistence.dto.TermDto;
 import eu.etaxonomy.cdm.persistence.query.MatchMode;
 import eu.etaxonomy.cdm.persistence.query.OrderHint;
 
-
 /**
  * @author a.kohlbecker
  * @since 29.05.2008
- * @version 1.0
  */
 @Repository
-public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> implements IDefinedTermDao{
-       private static final Logger logger = Logger.getLogger(DefinedTermDaoImpl.class);
+public class DefinedTermDaoImpl
+        extends IdentifiableDaoBase<DefinedTermBase>
+        implements IDefinedTermDao{
 
-       public DefinedTermDaoImpl() {
+    private static final Logger logger = Logger.getLogger(DefinedTermDaoImpl.class);
+
+       @SuppressWarnings("unchecked")
+    public DefinedTermDaoImpl() {
                super(DefinedTermBase.class);
                indexedClasses = new Class[25];
                indexedClasses[0] = Rank.class;
@@ -115,39 +117,29 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
 
        /**
         * Searches by Label
-        * @see eu.etaxonomy.cdm.persistence.dao.common.ITitledDao#findByTitle(java.lang.String)
         */
        @Override
-    public List<DefinedTermBase> findByTitle(String queryString) {
-               return findByTitle(queryString, null);
+    public List<DefinedTermBase> findByLabel(String queryString) {
+               return findByLabel(queryString, null);
        }
 
-
        /**
         * Searches by Label
-        * @see eu.etaxonomy.cdm.persistence.dao.common.ITitledDao#findByTitle(java.lang.String, eu.etaxonomy.cdm.model.common.CdmBase)
         */
        @Override
-    public List<DefinedTermBase> findByTitle(String queryString, CdmBase sessionObject) {
+    public List<DefinedTermBase> findByLabel(String queryString, CdmBase sessionObject) {
                checkNotInPriorView("DefinedTermDaoImpl.findByTitle(String queryString, CdmBase sessionObject)");
                Session session = getSession();
                if ( sessionObject != null ) {//attache the object to the session, TODO needed?
                        session.update(sessionObject);
                }
-               Query query = session.createQuery("select term from DefinedTermBase term join fetch term.representations representation where representation.label = :label");
+               Query query = session.createQuery("SELECT term "
+                       + " FROM DefinedTermBase term JOIN FETCH term.representations representation "
+                       + " WHERE representation.label = :label");
                query.setParameter("label", queryString);
-               return query.list();
-
-       }
-
-       @Override
-    public List<DefinedTermBase> findByTitleAndClass(String queryString, Class<DefinedTermBase> clazz) {
-               checkNotInPriorView("DefinedTermDaoImpl.findByTitleAndClass(String queryString, Class<DefinedTermBase> clazz)");
-               Session session = getSession();
-               Criteria crit = session.createCriteria(clazz);
-               crit.add(Restrictions.ilike("persistentTitleCache", queryString));
-               List<DefinedTermBase> results = crit.list();
-               return results;
+               @SuppressWarnings({ "unchecked", "rawtypes" })
+               List<DefinedTermBase> result = deduplicateResult(query.list());
+               return result;
        }
 
        @Override
@@ -159,11 +151,11 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                crit.setMaxResults(pagesize);
                int firstItem = (page - 1) * pagesize + 1;
                crit.setFirstResult(firstItem);
-               List<DefinedTermBase> results = crit.list();
+               @SuppressWarnings("unchecked")
+        List<DefinedTermBase> results = deduplicateResult(crit.list());
                return results;
        }
 
-
        @Override
     public Country getCountryByIso(String iso3166) {
                // If iso639 = "" query returns non-unique result. We prevent this here:
@@ -197,7 +189,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                addPageSizeAndNumber(criteria, pageSize, pageNumber);
 
                @SuppressWarnings("unchecked")
-        List<T> result = criteria.list();
+        List<T> result = deduplicateResult(criteria.list());
                return result;
        }
 
@@ -226,7 +218,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                addPageSizeAndNumber(criteria, pageSize, pageNumber);
 
                @SuppressWarnings("unchecked")
-        List<T> result = criteria.list();
+        List<T> result = deduplicateResult(criteria.list());
                return result;
        }
 
@@ -241,7 +233,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                addPageSizeAndNumber(criteria, pageSize, pageNumber);
 
                @SuppressWarnings("unchecked")
-               List<T> result = criteria.list();
+               List<T> result = deduplicateResult(criteria.list());
                return result;
        }
 
@@ -266,9 +258,9 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
 
                String queryStr;
                if (isIso639_1){
-                       queryStr = "from Language where iso639_1 = :isoCode";
+                       queryStr = "FROM Language WHERE iso639_1 = :isoCode";
                }else{
-                       queryStr = "from Language where idInVocabulary = :isoCode and vocabulary.uuid = :vocUuid";
+                       queryStr = "FROM Language WHERE idInVocabulary = :isoCode AND vocabulary.uuid = :vocUuid";
                }
                AuditEvent auditEvent = getAuditEventFromContext();
                if(auditEvent.equals(AuditEvent.CURRENT_VIEW)) {
@@ -297,7 +289,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         */
        @Override
     public List<Language> getLanguagesByIso(List<String> iso639List) {
-               List<Language> languages = new ArrayList<Language>(iso639List.size());
+               List<Language> languages = new ArrayList<>(iso639List.size());
                for (String iso639 : iso639List) {
                        languages.add(getLanguageByIso(iso639));
                }
@@ -306,7 +298,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
 
        @Override
     public List<Language> getLanguagesByLocale(Enumeration<Locale> locales) {
-               List<Language> languages = new ArrayList<Language>();
+               List<Language> languages = new ArrayList<>();
                while(locales.hasMoreElements()) {
                        Locale locale = locales.nextElement();
                        languages.add(getLanguageByIso(locale.getLanguage()));
@@ -358,7 +350,11 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
        @Override
     public List<Media> getMedia(DefinedTermBase definedTerm, Integer pageSize, Integer pageNumber) {
                checkNotInPriorView("DefinedTermDaoImpl.getMedia(DefinedTermBase definedTerm, Integer pageSize, Integer pageNumber)");
-               Query query = getSession().createQuery("select media from DefinedTermBase definedTerm join definedTerm.media media where definedTerm = :definedTerm");
+               Query query = getSession().createQuery(
+                          "SELECT media "
+                       + " FROM DefinedTermBase definedTerm "
+                       + " JOIN definedTerm.media media "
+                       + " WHERE definedTerm = :definedTerm");
                query.setParameter("definedTerm", definedTerm);
 
                addPageSizeAndNumber(query, pageSize, pageNumber);
@@ -385,7 +381,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                    addPageSizeAndNumber(criteria, pageSize, pageNumber);
 
                @SuppressWarnings("unchecked")
-               List<NamedArea> result = criteria.list();
+               List<NamedArea> result = deduplicateResult(criteria.list());
                return result;
                } else {
             AuditQuery query = makeAuditQuery(NamedArea.class, auditEvent);
@@ -399,7 +395,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                    }
 
                    @SuppressWarnings("unchecked")
-            List<NamedArea> result = query.getResultList();
+            List<NamedArea> result = deduplicateResult(query.getResultList());
                    return result;
                }
        }
@@ -423,7 +419,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                        addOrder(criteria,orderHints);
                        addPageSizeAndNumber(criteria, pageSize, pageNumber);
 
-                       result = criteria.list();
+                       result = deduplicateResult(criteria.list());
 
                } else {
                        AuditQuery query = getAuditReader().createQuery().forEntitiesAtRevision(NamedArea.class,
@@ -434,7 +430,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                        if (type != null) {
                                query.add(AuditEntity.relatedId("type").eq(type.getId()));
                        }
-                       result = query.getResultList();
+                       result = deduplicateResult(query.getResultList());
                }
 
                defaultBeanInitializer.initializeAll(result, propertyPaths);
@@ -490,7 +486,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                    addPageSizeAndNumber(query, pageSize, pageNumber);
 
                    @SuppressWarnings("unchecked")
-            List<T> result = query.list();
+            List<T> result = deduplicateResult(query.list());
                    return result;
                } else {
                         AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
@@ -499,7 +495,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                         addPageSizeAndNumber(query, pageSize, pageNumber);
 
              @SuppressWarnings("unchecked")
-             List<T> result = query.getResultList();
+             List<T> result = deduplicateResult(query.getResultList());
              return result;
                }
        }
@@ -517,17 +513,17 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                addPageSizeAndNumber(query, pageSize, pageNumber);
 
                    @SuppressWarnings("unchecked")
-            List<T> results = query.list();
+            List<T> results = deduplicateResult(query.list());
                    defaultBeanInitializer.initializeAll(results, propertyPaths);
                    return results;
                } else {
-                       List<T> result = new ArrayList<T>();
+                       List<T> result = new ArrayList<>();
                        for(T t : partOf) {
                                AuditQuery query = makeAuditQuery(DefinedTermBase.class, auditEvent);
                                query.add(AuditEntity.relatedId("partOf").eq(t.getId()));
                                addPageSizeAndNumber(query, pageSize, pageNumber);
 
-                           result.addAll(query.getResultList());
+                           result.addAll(deduplicateResult(query.getResultList()));
                        }
                        defaultBeanInitializer.initializeAll(result, propertyPaths);
                        return result;
@@ -592,7 +588,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
            query.setParameter("termType", termType);
 
            @SuppressWarnings("unchecked")
-        List<T> result = query.list();
+        List<T> result = deduplicateResult(query.list());
 
            defaultBeanInitializer.initializeAll(result, propertyPaths);
         return result;
@@ -605,7 +601,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
                Query query = getSession().createQuery("FROM " + clazz.getSimpleName());
 
            @SuppressWarnings("unchecked")
-        List<TERM> result = query.list();
+        List<TERM> result = deduplicateResult(query.list());
 
            defaultBeanInitializer.initializeAll(result, propertyPaths);
 
@@ -620,7 +616,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
     }
 
     /**
-     * Workaround for http://dev.e-taxonomy.eu/trac/ticket/5871 and #5945
+     * Workaround for https://dev.e-taxonomy.eu/redmine/issues/5871 and #5945
      * Terms with multiple representations return identical duplicates
      * due to eager representation loading. We expect these duplicates to appear
      * in line wo we only compare one term with its predecessor. If it already
@@ -628,7 +624,7 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
      * @param orginals
      * @return
      */
-    private <S extends DefinedTermBase<?>> List<S> deduplicateResult(List<S> orginals) {
+    protected static <S extends CdmBase> List<S> deduplicateResult(List<S> orginals) {
         List<S> result = new ArrayList<>();
         Iterator<S> it = orginals.iterator();
         S last = null;
@@ -644,48 +640,39 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         return result;
     }
 
+    @Override
+    public <S extends DefinedTermBase> List<S> list(Class<S> clazz, List<TermVocabulary> vocs, Integer limit, String pattern) {
+        return list(clazz, vocs, 0, limit, pattern, MatchMode.BEGINNING);
+    }
 
     @Override
-    public List<NamedArea> listNamedArea(List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode){
+    public <S extends DefinedTermBase> List<S> list(Class<S> clazz, List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode){
         Session session = getSession();
-//        Query query = null;
-//        if (pattern != null){
-//            if (vocs != null && !vocs.isEmpty()){
-//                query = session.createQuery("from NamedArea where titleCache like :pattern and vocabulary in :vocs ORDER BY titleCache");
-//                query.setParameterList("vocs", vocs);
-//            }else{
-//                query = session.createQuery("from NamedArea where titleCache like :pattern ORDER BY titleCache");
-//            }
-//            pattern = pattern.replace("*", "%");
-//            pattern = pattern.replace("?", "_");
-//            pattern = pattern + "%";
-//            query.setParameter("pattern", pattern);
-//
-//        } else {
-//            query = session.createQuery("FROM NamedArea WHERE vocabulary IN :vocs ORDER BY titleCache");
-//            query.setParameterList("vocs", vocs);
-//        }
-//        if (limit != null && limit > 0){
-//           query.setMaxResults(limit);
-//        }
-
-        Criteria crit = getSession().createCriteria(type, "namedArea");
+        if (clazz == null){
+            clazz = (Class)type;
+        }
+        Criteria crit = getSession().createCriteria(clazz, "term");
         if (!StringUtils.isBlank(pattern)){
+            crit.createAlias("term.representations", "reps");
+            Disjunction or = Restrictions.disjunction();
             if (matchmode == MatchMode.EXACT) {
-                crit.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(pattern)));
+                or.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(pattern)));
+                or.add(Restrictions.eq("reps.label", matchmode.queryStringFrom(pattern)));
             } else {
-    //          crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
-                crit.add(Restrictions.like("titleCache", matchmode.queryStringFrom(pattern)));
+                or.add(Restrictions.like("titleCache", matchmode.queryStringFrom(pattern)));
+                or.add(Restrictions.like("reps.label", matchmode.queryStringFrom(pattern)));
             }
+            crit.add(or);
         }
+
         if (limit != null && limit >= 0) {
             crit.setMaxResults(limit);
         }
 
         if (vocs != null &&!vocs.isEmpty()){
-            crit.createAlias("namedArea.vocabulary", "voc");
+            crit.createAlias("term.vocabulary", "voc");
             Disjunction or = Restrictions.disjunction();
-            for (TermVocabulary voc: vocs){
+            for (TermVocabulary<?> voc: vocs){
                 Criterion criterion = Restrictions.eq("voc.id", voc.getId());
                 or.add(criterion);
             }
@@ -696,25 +683,28 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         if (limit == null){
             limit = 1;
         }
-        int firstItem = (pageNumber - 1) * limit;
-
         crit.setFirstResult(0);
         @SuppressWarnings("unchecked")
-        List<NamedArea> results = crit.list();
+        List<S> results = deduplicateResult(crit.list());
         return results;
     }
 
+    @Override
+    public <S extends DefinedTermBase> List<S> listByAbbrev(Class<S> clazz, List<TermVocabulary> vocs, Integer limit, String pattern, TermSearchField type) {
+        return listByAbbrev(clazz, vocs, 0, limit, pattern, MatchMode.BEGINNING, type);
+    }
 
     @Override
-    public List<NamedArea> listNamedAreaByAbbrev(List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode, NamedAreaSearchField abbrevType){
-        Session session = getSession();
+    public <S extends DefinedTermBase> List<S> listByAbbrev(Class<S> clazz, List<TermVocabulary> vocs, Integer pageNumber, Integer limit, String pattern, MatchMode matchmode, TermSearchField abbrevType){
 
-        Criteria crit = getSession().createCriteria(type, "namedArea");
+        if (clazz == null){
+            clazz = (Class)type;
+        }
+        Criteria crit = getSession().createCriteria(clazz, "type");
         if (!StringUtils.isBlank(pattern)){
             if (matchmode == MatchMode.EXACT) {
                 crit.add(Restrictions.eq(abbrevType.getKey(), matchmode.queryStringFrom(pattern)));
             } else {
-    //          crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
                 crit.add(Restrictions.like(abbrevType.getKey(), matchmode.queryStringFrom(pattern)));
             }
         }
@@ -723,9 +713,9 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         }
 
         if (vocs != null &&!vocs.isEmpty()){
-            crit.createAlias("namedArea.vocabulary", "voc");
+            crit.createAlias("type.vocabulary", "voc");
             Disjunction or = Restrictions.disjunction();
-            for (TermVocabulary voc: vocs){
+            for (TermVocabulary<?> voc: vocs){
                 Criterion criterion = Restrictions.eq("voc.id", voc.getId());
                 or.add(criterion);
             }
@@ -736,45 +726,25 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         if (limit == null){
             limit = 1;
         }
-        int firstItem = (pageNumber - 1) * limit;
+//        int firstItem = (pageNumber - 1) * limit;
 
         crit.setFirstResult(0);
         @SuppressWarnings("unchecked")
-        List<NamedArea> results = crit.list();
+        List<S> results = deduplicateResult(crit.list());
         return results;
     }
 
-    @Override
-    public long count(List<TermVocabulary> vocs, String pattern){
-        Session session = getSession();
-        Query query = null;
-        if (pattern != null){
-            if (vocs != null && !vocs.isEmpty()){
-                query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE titleCache LIKE :pattern AND vocabulary IN :vocs");
-                query.setParameterList("vocs", vocs);
-            }else{
-                query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE titleCache LIKE :pattern ");
-            }
-            pattern = pattern.replace("*", "%");
-            pattern = pattern.replace("?", "_");
-            pattern = pattern + "%";
-            query.setParameter("pattern", pattern);
-
-        } else {
-            query = session.createQuery("SELECT COUNT(*) FROM NamedArea WHERE vocabulary IN :vocs");
-            query.setParameterList("vocs", vocs);
-        }
-
-
-        @SuppressWarnings("unchecked")
-        Long result = (Long) query.uniqueResult();
-        return result;
-    }
 
     @Override
     public Collection<TermDto> getIncludesAsDto(
             TermDto parentTerm) {
-        String queryString = TermDto.getTermDtoSelect()
+        String queryString;
+        if (parentTerm.getTermType().equals(TermType.NamedArea)){
+            queryString = TermDto.getTermDtoSelectNamedArea();
+        }else{
+            queryString = TermDto.getTermDtoSelect();
+        }
+        queryString = queryString
                 + "where a.partOf.uuid = :parentUuid";
         Query query =  getSession().createQuery(queryString);
         query.setParameter("parentUuid", parentTerm.getUuid());
@@ -787,10 +757,15 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
     }
 
     @Override
-    public Collection<TermDto> getKindOfsAsDto(
-            TermDto parentTerm) {
-        String queryString = TermDto.getTermDtoSelect()
-                + "where a.kindOf.uuid = :parentUuid";
+    public Collection<TermDto> getKindOfsAsDto(TermDto parentTerm) {
+
+        String queryString;
+        if (parentTerm.getTermType().equals(TermType.NamedArea)){
+            queryString = TermDto.getTermDtoSelectNamedArea();
+        }else{
+            queryString = TermDto.getTermDtoSelect();
+        }
+        queryString = queryString + "where a.kindOf.uuid = :parentUuid";
         Query query =  getSession().createQuery(queryString);
         query.setParameter("parentUuid", parentTerm.getUuid());
 
@@ -801,12 +776,13 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         return list;
     }
 
-
     @Override
     public Collection<TermDto> findByTitleAsDto(String title, TermType termType) {
         String queryString = TermDto.getTermDtoSelect()
                 + " where a.titleCache like :title "
                 + (termType!=null?" and a.termType = :termType ":"");
+
+        title = title.replace("*", "%");
         Query query =  getSession().createQuery(queryString);
         query.setParameter("title", "%"+title+"%");
         if(termType!=null){
@@ -820,6 +796,47 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         return list;
     }
 
+    @Override
+    public TermDto findByUUIDAsDto(UUID uuid) {
+        String queryString = TermDto.getTermDtoSelect()
+                + " where a.uuid like :uuid ";
+
+
+        Query query =  getSession().createQuery(queryString);
+        query.setParameter("uuid", uuid);
+
+
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
+
+        List<TermDto> list = TermDto.termDtoListFrom(result);
+        if (list.size()== 1){
+            return list.get(0);
+        }else{
+            return null;
+        }
+
+    }
+
+
+    @Override
+    public Collection<TermDto> findByTypeAsDto(TermType termType) {
+        if (termType == null){
+            return null;
+        }
+        String queryString = TermDto.getTermDtoSelect()
+                + " where a.termType = :termType ";
+        Query query =  getSession().createQuery(queryString);
+
+        query.setParameter("termType", termType);
+
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
+
+        List<TermDto> list = TermDto.termDtoListFrom(result);
+        return list;
+    }
+
     @Override
     public Collection<TermDto> findByUriAsDto(URI uri, String termLabel, TermType termType) {
         String queryString = TermDto.getTermDtoSelect()
@@ -843,47 +860,116 @@ public class DefinedTermDaoImpl extends IdentifiableDaoBase<DefinedTermBase> imp
         return list;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public List<NamedArea> listNamedArea(List<TermVocabulary> vocs, Integer limit, String pattern) {
+    public  Map<UUID, List<TermDto>> getSupportedStatesForFeature(Set<UUID> featureUuids){
+        Map<UUID, List<TermDto>> map = new HashMap<>();
+        for (UUID featureUuid: featureUuids){
+            List<TermDto> list = new ArrayList<>();
+            String supportedCategoriesQueryString = "SELECT cat.uuid "
+                    + "from DefinedTermBase t "
+                    + "join t.supportedCategoricalEnumerations as cat "
+                    + "where t.uuid = :featureUuid";
+            Query supportedCategoriesQuery =  getSession().createQuery(supportedCategoriesQueryString);
+            supportedCategoriesQuery.setParameter("featureUuid", featureUuid);
+            @SuppressWarnings("unchecked")
+               List<UUID> supportedCategories = supportedCategoriesQuery.list();
+            if(supportedCategories.isEmpty()){
+                map.put(featureUuid, list);
+                continue;
+            }
+
+            String queryString = TermDto.getTermDtoSelect()
+                    + "where v.uuid in (:supportedCategories) "
+                    + "order by a.titleCache";
+            Query query =  getSession().createQuery(queryString);
+            query.setParameterList("supportedCategories", supportedCategories);
 
-        return listNamedArea(vocs, 0, limit, pattern, MatchMode.BEGINNING);
+            @SuppressWarnings("unchecked")
+            List<Object[]> result = query.list();
 
+            list = TermDto.termDtoListFrom(result);
+            map.put(featureUuid, list);
+        }
+        return map;
     }
 
     @Override
-    public List<NamedArea> listNamedAreaByAbbrev(List<TermVocabulary> vocs, Integer limit, String pattern, NamedAreaSearchField type) {
+    public Collection<TermDto> findByUUIDsAsDto(List<UUID> uuidList) {
+        List<TermDto> list = new ArrayList<>();
+        if (uuidList == null || uuidList.isEmpty()){
+            return null;
+        }
 
-        return listNamedAreaByAbbrev(vocs, 0, limit, pattern, MatchMode.BEGINNING, type);
+        String queryString = TermDto.getTermDtoSelect()
+                + "where a.uuid in :uuidList "
+                + "order by a.titleCache";
+        Query query =  getSession().createQuery(queryString);
+        query.setParameterList("uuidList", uuidList);
+
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
 
+        list = TermDto.termDtoListFrom(result);
+        return list;
     }
 
     @Override
-    public List<TermDto> getSupportedStatesForFeature(UUID featureUuid){
+    public Collection<TermDto> findFeatureByUUIDsAsDto(List<UUID> uuidList) {
         List<TermDto> list = new ArrayList<>();
-        DefinedTermBase load = load(featureUuid);
-        if(load instanceof Feature){
-            Set<UUID> vocabularyUuids =
-                    ((Feature) load).getSupportedCategoricalEnumerations().stream()
-                    .map(catEnum->catEnum.getUuid())
-                    .collect(Collectors.toSet());
-            if(vocabularyUuids.isEmpty()){
-                return list;
-            }
-            String queryString = TermDto.getTermDtoSelect()
-                    + "where v.uuid in :vocabularyUuids "
-                    + "order by a.titleCache";
-            Query query =  getSession().createQuery(queryString);
-            query.setParameterList("vocabularyUuids", vocabularyUuids);
+        if (uuidList == null || uuidList.isEmpty()){
+            return null;
+        }
 
-            @SuppressWarnings("unchecked")
-            List<Object[]> result = query.list();
+        String queryString = FeatureDto.getTermDtoSelect()
+                + "where a.uuid in :uuidList "
+                + "order by a.titleCache";
+        Query query =  getSession().createQuery(queryString);
+        query.setParameterList("uuidList", uuidList);
 
-            list = TermDto.termDtoListFrom(result);
-        }
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
+
+        list = FeatureDto.termDtoListFrom(result);
         return list;
     }
 
-}
+    @Override
+    public Collection<TermDto> findFeatureByTitleAsDto(String pattern) {
+        String queryString = FeatureDto.getTermDtoSelect()
+                + " where a.titleCache like :title "
+                +  " and a.termType = :termType ";
+
+        pattern = pattern.replace("*", "%");
+        Query query =  getSession().createQuery(queryString);
+        query.setParameter("title", "%"+pattern+"%");
+        query.setParameter("termType", TermType.Feature);
+
+
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
+
+        List<TermDto> list = FeatureDto.termDtoListFrom(result);
+        return list;
+    }
+
+    @Override
+    public TermDto getTermDto(UUID uuid) {
+        String queryString = TermDto.getTermDtoSelect()
+                + " where a.uuid = :uuid ";
+
+
+        Query query =  getSession().createQuery(queryString);
+        query.setParameter("uuid", uuid);
+
+
+
+        @SuppressWarnings("unchecked")
+        List<Object[]> result = query.list();
+        TermDto dto = null;
+        List<TermDto> dtoList = TermDto.termDtoListFrom(result);
+        if (dtoList != null && !dtoList.isEmpty()){
+            dto = dtoList.get(0);
+        }
+        return dto;
+    }
+}
\ No newline at end of file