implement getTermVocabulariesByTermClasses also for subclasses (#2704)
authorAndreas Müller <a.mueller@bgbm.org>
Tue, 3 Jan 2012 18:55:29 +0000 (18:55 +0000)
committerAndreas Müller <a.mueller@bgbm.org>
Tue, 3 Jan 2012 18:55:29 +0000 (18:55 +0000)
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/common/ITermVocabularyDao.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/common/TermVocabularyDaoImpl.java
cdmlib-persistence/src/test/java/eu/etaxonomy/cdm/persistence/dao/hibernate/common/TermVocabularyDaoImplTest.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/IVocabularyService.java
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/VocabularyServiceImpl.java

index 0fb851da1735fa1c2e554b93227036d647a2facd..28df89312af48af3baa7e5fdbefbd15694ae2cb3 100644 (file)
@@ -61,8 +61,9 @@ public interface ITermVocabularyDao extends IIdentifiableDao<TermVocabulary> {
        /**\r
      * Returns term vocabularies that contain terms of a certain class e.g. Feature, Modifier, State.\r
      * \r
-     * @param <TERM>\r
+     * @param <TERMTYPE>\r
      * @param clazz the term class of the terms in the vocabulary\r
+     * @param includeSubclasses if <code>true</code> all subclasses of clazz will be included for computation of the result\r
      * @param limit The maximum number of vocabularies returned (can be null for all vocabularies)\r
      * @param start The offset from the start of the result set (0 - based, can be null - equivalent of starting at the beginning of the recordset)\r
      * @param orderHints \r
@@ -72,5 +73,6 @@ public interface ITermVocabularyDao extends IIdentifiableDao<TermVocabulary> {
      * @param propertyPaths properties to be initialized\r
      * @return a list of term vocabularies\r
      */\r
-       <TERM extends DefinedTermBase> List<TermVocabulary<TERM>> listByTermClass(Class<TERM> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
+       <TERMTYPE extends DefinedTermBase> List<TermVocabulary<? extends TERMTYPE>> listByTermClass(Class<TERMTYPE> clazz, boolean includeSubclasses, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
+\r
 }\r
index d3d9e7e98d05d9e0c9e536f8f183efa3ba0b5234..fd4266ffc3fe22b4e5d3f0ae9e02d4bcb9878516 100644 (file)
@@ -139,4 +139,44 @@ public class TermVocabularyDaoImpl extends IdentifiableDaoBase<TermVocabulary> i
            defaultBeanInitializer.initializeAll(result, propertyPaths);\r
                return result;\r
        }\r
+       \r
+       public <TERM extends DefinedTermBase> List<TermVocabulary<? extends TERM>> listByTermClass(Class<TERM> clazz, boolean includeSubclasses, Integer limit, Integer start,List<OrderHint> orderHints, List<String> propertyPaths) {\r
+               checkNotInPriorView("TermVocabularyDao.listByTermClass2(Class<TERM> clazz, Integer limit, Integer start,        List<OrderHint> orderHints, List<String> propertyPaths)");\r
+               List<Integer> intermediateResults;\r
+               \r
+               if (includeSubclasses){\r
+                       String hql = " SELECT DISTINCT trm.vocabulary.id " +\r
+                                       " FROM %s trm " +\r
+                                       " GROUP BY trm.vocabulary ";\r
+                       hql = String.format(hql, clazz.getSimpleName());\r
+                       Query query = getSession().createQuery(hql);\r
+                       intermediateResults = query.list();\r
+               }else{\r
+                       Criteria criteria = getSession().createCriteria(type);\r
+                       criteria.createAlias("terms", "trms").add(Restrictions.eq("trms.class", clazz.getSimpleName()));                \r
+                       criteria.setProjection(Projections.id());\r
+                       intermediateResults = criteria.list();\r
+               }\r
+                       \r
+               if(intermediateResults.size() == 0) {\r
+                       return new ArrayList<TermVocabulary<? extends TERM>>();\r
+               }\r
+               \r
+               Criteria criteria = getSession().createCriteria(type);\r
+               criteria.add(Restrictions.in("id", intermediateResults));\r
+               \r
+               if(limit != null) {\r
+                   criteria.setMaxResults(limit);\r
+               if(start != null) {\r
+                   criteria.setFirstResult(start);\r
+               }\r
+               }\r
+               \r
+               this.addOrder(criteria, orderHints);\r
+               \r
+               List<TermVocabulary<? extends TERM>> result = (List<TermVocabulary<? extends TERM>>)criteria.list();\r
+           defaultBeanInitializer.initializeAll(result, propertyPaths);\r
+               return result;\r
+       }\r
+\r
 }\r
index 74b4e4a0c29db755db6c7563fe8733b0893f1bdd..1a791099b32e454adfe2d15992358c0b38ac371c 100644 (file)
@@ -19,7 +19,13 @@ import org.junit.Before;
 import org.junit.Test;\r
 import org.unitils.spring.annotation.SpringBeanByType;\r
 \r
+import com.mchange.util.AssertException;\r
+\r
 import eu.etaxonomy.cdm.model.common.TermVocabulary;\r
+import eu.etaxonomy.cdm.model.location.Continent;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
+import eu.etaxonomy.cdm.model.location.TdwgArea;\r
+import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
 import eu.etaxonomy.cdm.persistence.dao.common.ITermVocabularyDao;\r
 import eu.etaxonomy.cdm.test.integration.CdmIntegrationTest;\r
@@ -39,13 +45,31 @@ public class TermVocabularyDaoImplTest extends CdmIntegrationTest {
        @Before\r
        public void setUp() {\r
        }\r
-       \r
+\r
        @Test\r
        public void testListVocabularyByClass() {\r
-               List<TermVocabulary<Rank>> rankVocabularies = dao.listByTermClass(Rank.class, null, null, null, null);\r
+               //test class with no subclasses\r
+               List<TermVocabulary<? extends Rank>> rankVocabularies = dao.listByTermClass(Rank.class, false, null, null, null, null);\r
+               assertFalse("There should be at least one vocabulary containing terms of class Rank",rankVocabularies.isEmpty());\r
+               assertEquals("There should be only one vocabulary containing terms of class Rank",1,rankVocabularies.size());\r
                \r
+               \r
+               rankVocabularies = dao.listByTermClass(Rank.class, true, null, null, null, null);\r
                assertFalse("There should be at least one vocabulary containing terms of class Rank",rankVocabularies.isEmpty());\r
                assertEquals("There should be only one vocabulary containing terms of class Rank",1,rankVocabularies.size());\r
+               \r
+               //with subclasses\r
+               List<TermVocabulary<? extends NamedArea>> namedAreaVocabularies = dao.listByTermClass(NamedArea.class, true, null, null, null, null);\r
+               int subclassedSize = namedAreaVocabularies.size();\r
+               assertEquals("There should be 3 vocabularies (TdwgAreas, Continents, WaterbodyOrCountries)", 3, subclassedSize);\r
+               \r
+               List<TermVocabulary<? extends NamedArea>> namedAreaOnlyVocabularies = dao.listByTermClass(NamedArea.class, false, null, null, null, null);\r
+               List<TermVocabulary<? extends TdwgArea>> tdwgVocabularies = dao.listByTermClass(TdwgArea.class, false, null, null, null, null);\r
+               List<TermVocabulary<? extends WaterbodyOrCountry>> countryVocabularies = dao.listByTermClass(WaterbodyOrCountry.class, false, null, null, null, null);\r
+               List<TermVocabulary<? extends Continent>> continentVocabularies = dao.listByTermClass(Continent.class, false, null, null, null, null);\r
+               int sumOfSingleSizes = namedAreaOnlyVocabularies.size() + tdwgVocabularies.size() + countryVocabularies.size() + continentVocabularies.size();\r
+               assertEquals("number of NamedArea and subclasses should be same as sum of all single vocabularies", subclassedSize, sumOfSingleSizes);\r
+               \r
        }\r
        \r
 }\r
index 56fb198591701c96d9ec507b8eb6bef66206e93c..2533e1f89c90f9aad5ebfe40ee93cf1441d54f5f 100644 (file)
@@ -10,7 +10,6 @@
 package eu.etaxonomy.cdm.api.service;\r
 \r
 import java.util.List;\r
-import java.util.UUID;\r
 \r
 import eu.etaxonomy.cdm.api.service.pager.Pager;\r
 import eu.etaxonomy.cdm.model.common.DefinedTermBase;\r
@@ -36,8 +35,28 @@ public interface IVocabularyService extends IIdentifiableEntityService<TermVocab
         *            authorTeam.persistentTitleCache\r
      * @param propertyPaths properties to be initialized\r
      * @return a list of term vocabularies\r
+     * @see #listByTermClass(Class, boolean, Integer, Integer, List, List)\r
      */\r
        public <TERM extends DefinedTermBase> List<TermVocabulary<TERM>> listByTermClass(Class<TERM> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
+\r
+          /**\r
+     * Returns term vocabularies that contain terms of a certain class e.g. Feature, Modifier, State.\r
+     * \r
+     * @param <TERM>\r
+     * @param clazz the term class of the terms in the vocabulary\r
+     * @param includeSubclasses if <code>true</code> all subclasses of clazz will be included for computation of the result\r
+     * @param limit The maximum number of vocabularies returned (can be null for all vocabularies)\r
+     * @param start The offset from the start of the result set (0 - based, can be null - equivalent of starting at the beginning of the recordset)\r
+     * @param orderHints \r
+     *            Supports path like <code>orderHints.propertyNames</code> which\r
+        *            include *-to-one properties like createdBy.username or\r
+        *            authorTeam.persistentTitleCache\r
+     * @param propertyPaths properties to be initialized\r
+     * @return a list of term vocabularies\r
+     * @see #listByTermClass(Class, Integer, Integer, List, List)\r
+     */\r
+       public <TERM extends DefinedTermBase> List<TermVocabulary<? extends TERM>> listByTermClass(Class<TERM> clazz, boolean includeSubclasses, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths);\r
+\r
        \r
        /**\r
         * Returns Language Vocabulary\r
index b3fa949e8dfd507af24d88b6afa02db128b30410..e8475000dffdb0d4500144cf0cc063c7aba53415 100644 (file)
@@ -55,9 +55,18 @@ public class VocabularyServiceImpl extends IdentifiableServiceBase<TermVocabular
                return dao.findByUuid(vocabularyType.getUuid());\r
        }\r
        \r
+       /* (non-Javadoc)\r
+        * @see eu.etaxonomy.cdm.api.service.IVocabularyService#listByTermClass(java.lang.Class, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)\r
+        */\r
+       @Override\r
        public <TERM extends DefinedTermBase> List<TermVocabulary<TERM>> listByTermClass(Class<TERM> clazz, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
-               return dao.listByTermClass(clazz, limit, start, orderHints, propertyPaths);\r
+               boolean includeSubclasses = false;\r
+               return (List)listByTermClass(clazz, includeSubclasses, limit, start, orderHints, propertyPaths);\r
        }       \r
+\r
+       public <TERM extends DefinedTermBase> List<TermVocabulary<? extends TERM>> listByTermClass(Class<TERM> clazz, boolean includeSubclasses, Integer limit, Integer start, List<OrderHint> orderHints, List<String> propertyPaths) {\r
+               return dao.listByTermClass(clazz, includeSubclasses, limit, start, orderHints, propertyPaths);\r
+       }\r
        \r
        /** \r
         * (non-Javadoc)\r