ref #10400 implemented current/preferred determination as additional assoziation...
authorAndreas Müller <a.mueller@bgbm.org>
Wed, 24 Jan 2024 13:54:01 +0000 (14:54 +0100)
committerAndreas Müller <a.mueller@bgbm.org>
Wed, 24 Jan 2024 13:55:32 +0000 (14:55 +0100)
cdmlib-api/src/main/java/eu/etaxonomy/cdm/api/filter/TaxonOccurrenceRelationType.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/occurrence/DeterminationEvent.java
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/dao/hibernate/occurrence/OccurrenceDaoHibernateImpl.java
cdmlib-persistence/src/test/java/eu/etaxonomy/cdm/persistence/dao/hibernate/occurrence/OccurrenceDaoHibernateImplTest.java

index ac6b0d524a6c3d8c2adddcacd9d5ebe7476821c6..63eeefe11ed2dcd492bdf2cd263405500c66a2c3 100644 (file)
@@ -13,6 +13,8 @@ import java.util.EnumSet;
 /**
  * Enumeration to define a filter for taxon-occurrence associations.
  *
+ * See also https://dev.e-taxonomy.eu/redmine/issues/10400
+ *
  * @author muellera
  * @since 20.01.2024
  */
@@ -20,6 +22,7 @@ public enum TaxonOccurrenceRelationType {
 
     IndividualsAssociation("IA"),
     Determination("DET"),
+    CurrentDetermination("CDET"),  //only relevant if DET is not used as CurrentDetermination is a subset of Determination
     TypeDesignation("TD");
 
     private String key;
@@ -45,6 +48,9 @@ public enum TaxonOccurrenceRelationType {
     public static EnumSet<TaxonOccurrenceRelationType> Determinations(){
         return EnumSet.of(Determination);
     }
+    public static EnumSet<TaxonOccurrenceRelationType> CurrentDeterminations(){
+        return EnumSet.of(CurrentDetermination);
+    }
     public static EnumSet<TaxonOccurrenceRelationType> TypeDesignations(){
         return EnumSet.of(TypeDesignation);
     }
@@ -57,7 +63,4 @@ public enum TaxonOccurrenceRelationType {
         }
         return null;
     }
-
-
-
-}
+}
\ No newline at end of file
index c7cf901049503f581f33a65e2f5be7b31560a614..8a80e8d4ca68e507d81fa3a224fa1131fe4a91f9 100644 (file)
@@ -37,6 +37,7 @@ import eu.etaxonomy.cdm.model.agent.AgentBase;
 import eu.etaxonomy.cdm.model.common.EventBase;
 import eu.etaxonomy.cdm.model.name.TaxonName;
 import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.term.DefinedTerm;
@@ -128,6 +129,14 @@ public class DeterminationEvent extends EventBase {
                return result;
        }
 
+    public static DeterminationEvent NewInstance(Synonym synonym, SpecimenOrObservationBase identifiedUnit ){
+        DeterminationEvent result = new DeterminationEvent();
+        result.setTaxon(synonym);
+        result.setIdentifiedUnit(identifiedUnit);
+        identifiedUnit.addDetermination(result);
+        return result;
+    }
+
 //*********************** CONSTRUCTOR ********************************/
 
     //for hibernate use only, *packet* private required by bytebuddy
index 69853dacb282b04971582bb1a9a04fd3fbe347b7..2e464ab3ed7d102c516ddc86c5394d37ba7e7e51 100644 (file)
@@ -735,8 +735,10 @@ public class OccurrenceDaoHibernateImpl
         //Note: we don't pass limits and order to individual results query as the data is merged with other results
 
         //add determinations
-        if (taxonOccurrenceRelTypes.contains(TaxonOccurrenceRelationType.Determination)) {
-            List<Integer> detResults = addAssociatedDeterminations(clazz, associatedTaxon);
+        if (taxonOccurrenceRelTypes.contains(TaxonOccurrenceRelationType.Determination)
+                || taxonOccurrenceRelTypes.contains(TaxonOccurrenceRelationType.CurrentDetermination)) {
+            boolean currentOnly = !taxonOccurrenceRelTypes.contains(TaxonOccurrenceRelationType.Determination);
+            List<Integer> detResults = addAssociatedDeterminations(clazz, associatedTaxon, currentOnly);
             setOfAllIds.addAll(detResults);
         }
 
@@ -829,7 +831,7 @@ public class OccurrenceDaoHibernateImpl
      * Computes the IDs of the specimen associated with a taxon via determinations
      */
     private List<Integer> addAssociatedDeterminations(Class<? extends SpecimenOrObservationBase> clazz,
-            Taxon associatedTaxon) {
+            Taxon associatedTaxon, boolean currentOnly) {
 
         Criteria criteria = null;
         if(clazz == null) {
@@ -839,6 +841,9 @@ public class OccurrenceDaoHibernateImpl
         }
 
         Criteria determinationsCriteria = criteria.createCriteria("determinations");
+        if (currentOnly) {
+            determinationsCriteria.add(Restrictions.eq("preferredFlag", Boolean.TRUE));
+        }
 
         Disjunction determinationOr = Restrictions.disjunction();
 
index 451eb4083d870571cb9391a39ca76ed23658f395..d26760862806c861e15ba274cda4aa7e6b60d688 100644 (file)
@@ -182,7 +182,7 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
         final EnumSet<TaxonOccurrenceRelationType> taxonOccRelType = TaxonOccurrenceRelationType.All();
 
         //load data
-           //TODO empty
+           //TODO make DB empty
            Taxon taxon = createListByAssociationTestData();
         this.commitAndStartNewTransaction();
 
@@ -191,13 +191,13 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
         List<SpecimenOrObservationBase> associatedUnits = dao.listByAssociatedTaxon(
                 type, taxon, included_unpublished, taxonOccRelType,
                 limit, start, orderHints, propertyPaths);
-        Assert.assertEquals("All directly associated specimen should be attached", 6, associatedUnits.size());
+        Assert.assertEquals("All directly associated specimen should be attached", 7, associatedUnits.size());
 
         //test published only
         associatedUnits = dao.listByAssociatedTaxon(
                 type, taxon, no_unpublished, taxonOccRelType,
                 limit, start, orderHints, propertyPaths);
-        Assert.assertEquals("All published directly associated specimen should be attached", 5, associatedUnits.size());
+        Assert.assertEquals("All published directly associated specimen should be attached", 6, associatedUnits.size());
 
         //test include individual associations
         associatedUnits = dao.listByAssociatedTaxon(
@@ -209,6 +209,12 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
         associatedUnits = dao.listByAssociatedTaxon(
                 type, taxon, included_unpublished, TaxonOccurrenceRelationType.Determinations(),
                 limit, start, orderHints, propertyPaths);
+        Assert.assertEquals("Only specimen associated via determination should be attached", 2, associatedUnits.size());
+
+        //test include current determinations only
+        associatedUnits = dao.listByAssociatedTaxon(
+                type, taxon, included_unpublished, TaxonOccurrenceRelationType.CurrentDeterminations(),
+                limit, start, orderHints, propertyPaths);
         Assert.assertEquals("Only specimen associated via determination should be attached", 1, associatedUnits.size());
 
         //test include type specimens
@@ -225,6 +231,7 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
                 limit, start, titleCacheOrder, propertyPaths);
         @SuppressWarnings("rawtypes")
         Iterator<SpecimenOrObservationBase> iterator = associatedUnits.iterator();
+        Assert.assertEquals("FieldUnit 3", iterator.next().getTitleCache());
         Assert.assertEquals("Specimen Accepted Name Type", iterator.next().getTitleCache());
         Assert.assertEquals("Specimen Determination", iterator.next().getTitleCache());
         Assert.assertEquals("Specimen Heterotypic Name Type 1", iterator.next().getTitleCache());
@@ -234,35 +241,37 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
 
         //test limit + start
         int myLimit = 3;
-        int myStart = 1;
+        int myStart = 2;
         associatedUnits = dao.listByAssociatedTaxon(
                 type, taxon, included_unpublished, taxonOccRelType,
                 myLimit, myStart, titleCacheOrder, propertyPaths);
         Assert.assertEquals(myLimit, associatedUnits.size());
         iterator = associatedUnits.iterator();
-//        Assert.assertEquals("Specimen Accepted Name Type", iterator.next().getTitleCache());
+        //this is a subset of the above test
         Assert.assertEquals("Specimen Determination", iterator.next().getTitleCache());
         Assert.assertEquals("Specimen Heterotypic Name Type 1", iterator.next().getTitleCache());
         Assert.assertEquals("Specimen Heterotypic Name Type 2", iterator.next().getTitleCache());
-//        Assert.assertEquals("Specimen Homotypic Name Type", iterator.next().getTitleCache());
-//        Assert.assertEquals("Specimen Individual Association", iterator.next().getTitleCache());
 
         //test type
+        //... type all classes (default)
         Taxon fieldUnitTaxon = (Taxon)taxonDao.load(uuid_fieldUnitTaxon);
         associatedUnits = dao.listByAssociatedTaxon(
                 type, fieldUnitTaxon, included_unpublished, taxonOccRelType,
                 limit, start, orderHints, propertyPaths);
         //TODO do we really want to have the type of the homotypic synonym here
         //     though it is not explicitly mentioned in the synonymy of field unit taxon?
-        Assert.assertEquals("Only field unit and the 2 derived units associated to the name "
-                + " and its homotypic group via type designation should be returned for field unit taxon",
+        Assert.assertEquals("Only field unit 1 (added via ind. ass.) and the 2 derived units "
+                + " associated to the name and its homotypic group via type designation "
+                + " should be returned for field unit taxon",
                 3, associatedUnits.size());
 
+        //... test type = FieldUnit.class
         List<FieldUnit> fieldUnits = dao.listByAssociatedTaxon(
                 FieldUnit.class, fieldUnitTaxon, included_unpublished, taxonOccRelType,
                 limit, start, orderHints, propertyPaths);
         Assert.assertEquals("Only the field unit 1 should be attached to field unit taxon", 1, fieldUnits.size());
 
+        //... test type = DerivedUnit.class
         List<DerivedUnit> derivedUnits = dao.listByAssociatedTaxon(
                 DerivedUnit.class, fieldUnitTaxon, included_unpublished, taxonOccRelType,
                 limit, start, orderHints, propertyPaths);
@@ -270,7 +279,7 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
                 + " be attached to field unit taxon", 2, derivedUnits.size());
 
         //test synonyms
-        //TODO
+        //TODO not yet available in listByAssociatedTaxon()
 //        Synonym heteroSyn_1 = (Synonym)taxonDao.load(uuid_hetero_syn_1);
 //        associatedUnits = dao.listByAssociatedTaxon(
 //                type, heteroSyn_1, included_unpublished, taxonOccRelType,
@@ -300,7 +309,7 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
 
             //homotypic synonym
             TaxonName name2 = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES(), "Pinus", null, "alba", null, null, null, null, null);
-            Synonym homoSyn = taxon.addHomotypicSynonymName(name2);
+            taxon.addHomotypicSynonymName(name2);
 
             //heterotypic group
             TaxonName name3 = TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES(), "Abies", null, "pinus", null, null, null, null, null);
@@ -349,20 +358,27 @@ public class OccurrenceDaoHibernateImplTest extends CdmTransactionalIntegrationT
             fu1.setTitleCache("FieldUnit 1", true);
             FieldUnit fu2 = DerivedUnitFacade.NewInstance(du_determination).getFieldUnit(true);
             FieldUnit fu3 = DerivedUnitFacade.NewInstance(du_accType).getFieldUnit(true);
+            fu3.setTitleCache("FieldUnit 3", true);
             FieldUnit fu4 = DerivedUnitFacade.NewInstance(du_homonymType).getFieldUnit(true);
             dao.save(fu1);
             dao.save(fu2);
             dao.save(fu3);
             dao.save(fu4);
 
+            //*** Add assoziations ****
+
             //du1 is added as indiv. association
             TaxonDescription td = TaxonDescription.NewInstance(taxon);
             IndividualsAssociation ia = IndividualsAssociation.NewInstance(du_indAss);
             td.addElement(ia);
 
-            //du2 is added as determination
+            //du2 is assoziated as determination
             DeterminationEvent.NewInstance(taxon, du_determination);
 
+            //fu3 is assoziated with name3 (first heterotypic synonym) as current determination
+            DeterminationEvent de = DeterminationEvent.NewInstance(heteroSyn1.getName(), fu3);
+            de.setPreferredFlag(true);
+
             //du3 is added as type designation for the accepted taxon
             name1.addSpecimenTypeDesignation(du_accType, SpecimenTypeDesignationStatus.HOLOTYPE(), null, null, null, false, false);