new functionality for homotypical group
authorAndreas Müller <a.mueller@bgbm.org>
Thu, 18 Jun 2009 14:51:05 +0000 (14:51 +0000)
committerAndreas Müller <a.mueller@bgbm.org>
Thu, 18 Jun 2009 14:51:05 +0000 (14:51 +0000)
.gitattributes
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/HomotypicalGroup.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/NameRelationshipType.java
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/TaxonNameBase.java
cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/HomotypicalGroupTest.java [new file with mode: 0644]

index 591aa3a03cc92de72ebc093f12188d248082b500..d9b65aa1f5665ea8faeef36261729e900ea4b5d6 100644 (file)
@@ -1249,6 +1249,7 @@ cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/description/PresenceAbsenceTer
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/description/TextDataTest.java -text
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/location/TdwgAreaTest.java -text
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/BotanicalNameTest.java -text
+cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/HomotypicalGroupTest.java -text
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/NameTypeDesignationStatusTest.java -text
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/NameTypeDesignationTest.java -text
 cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/NomenclaturalStatusTypeTest.java -text
index 707d8f6654b26cdfbd6430ce06d152fc2fe9926f..892f53ef57bab54f1af74ed8d09e4d3a58a8e72a 100644 (file)
@@ -370,4 +370,88 @@ public class HomotypicalGroup extends AnnotatableEntity {
                Collections.sort(result, new TaxonComparator());
                return result;
        }
+
+       
+       
+       
+       /**
+        * Returns all taxon names in the homotypical group that have a 'is_basionym_for' (zool.: 'is_original_combination_for') relationship.
+        * @return
+        */
+       public Set<TaxonNameBase> getBasionyms(){
+               Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(true, false);
+               Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
+               for (NameRelationship nameRelationship : set){
+                       result.add(nameRelationship.getFromName());
+               }
+               return result;
+       }
+
+       /**
+        * Returns all taxon names in the homotypical group that have a 'is_replaced_synonym_for' relationship.
+        * @return
+        */
+       public Set<TaxonNameBase> getReplacedSynonym(){
+               Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(false, true);
+               Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
+               for (NameRelationship nameRelationship : set){
+                       result.add(nameRelationship.getFromName());
+               }
+               return result;
+       }
+       
+       /**
+        * Returns the name relationships that represent either a basionym (original combination) relationship or
+        * a replaced synonym relationship.  
+        * @return
+        */
+       public Set<NameRelationship> getBasionymAndReplacedSynonymRelations(){
+               return getBasionymOrReplacedSynonymRelations(true, true);
+       }
+       
+       private Set<NameRelationship> getBasionymOrReplacedSynonymRelations(boolean doBasionym, boolean doReplacedSynonym){
+               Set<NameRelationship> result = new HashSet<NameRelationship>(); 
+               Set<TaxonNameBase> names = this.getTypifiedNames();
+               if (names.size() > 1){
+                       for (TaxonNameBase name : names){
+                               Set nameRels = name.getNameRelations();
+                               //TODO make getNameRelations generic
+                               for (Object obj : nameRels){
+                                       NameRelationship nameRel = (NameRelationship)obj;
+                                       NameRelationshipType type = nameRel.getType();
+                                       if ( type.isBasionymRelation() && doBasionym){
+                                               if (testRelatedNameInThisGroup(nameRel)){
+                                                       result.add(nameRel);
+                                               }else{
+                                                       logger.warn("Name has basionym relation to a name that is not in the same homotypical group");
+                                               }
+                                       }else if (type.isReplacedSynonymRelation() && doReplacedSynonym)  {
+                                               if (testRelatedNameInThisGroup(nameRel)){
+                                                       result.add(nameRel);
+                                               }else{
+                                                       logger.warn("Name has replaced synonym relation to a name that is not in the same homotypical group");
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return result;
+       }
+       
+       private boolean testRelatedNameInThisGroup(NameRelationship nameRel){
+               TaxonNameBase toName = nameRel.getToName();
+               return (this.getTypifiedNames().contains(toName));
+       }
+       
+       private boolean isBasionymOrRepSynRel(NameRelationshipType relType){
+               if (relType == null){
+                       throw new IllegalArgumentException("NameRelationshipType should never be null");
+               }else if (relType.equals(NameRelationshipType.BASIONYM())) {
+                       return true;
+               }else if (relType.equals(NameRelationshipType.REPLACED_SYNONYM())){
+                       return true;
+               }else{
+                       return false;
+               }
+       }
 }
index 93d82c0db3f411f7492a8570eff55d03021627c4..3ef8720f7bcc0f707761953293779f9d3cf5b1d4 100644 (file)
@@ -201,6 +201,22 @@ public class NameRelationshipType extends RelationshipTermBase<NameRelationshipT
                        return false;
                }
        }
+       
+       @Transient
+       public boolean isBasionymRelation(){
+               if (BASIONYM() == null){
+                       throw new IllegalStateException("NameRelationships have not been initialized yet. Please initialize DefinedTerms first");
+               }
+               return this.equals(BASIONYM());
+       }
+       
+       @Transient
+       public boolean isReplacedSynonymRelation(){
+               if (REPLACED_SYNONYM() == null){
+                       throw new IllegalStateException("NameRelationships have not been initialized yet. Please initialize DefinedTerms first");
+               }
+               return this.equals(REPLACED_SYNONYM());
+       }
 
        
        /**
index dc58e9dcdd527f37e34123c5833ef93367e457dd..86d0f3fb6a37e9e3fbb30db3a5d07eb162965854 100644 (file)
@@ -47,6 +47,7 @@ import eu.etaxonomy.cdm.model.common.IReferencedEntity;
 import eu.etaxonomy.cdm.model.common.IRelated;
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
 import eu.etaxonomy.cdm.model.common.RelationshipBase;
+import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
 import eu.etaxonomy.cdm.model.occurrence.Specimen;
 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
@@ -337,11 +338,31 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
         * @see                                   #addNameRelationship(NameRelationship)
         */
        public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
-               NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
+               addRelationshipToName(toName, type, null, null, ruleConsidered);
+               //              NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
        }
        
-       public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
+       /**
+        * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from <i>this</i> taxon name to another taxon name
+        * and adds it both to the set of {@link #getRelationsFromThisName() relations from <i>this</i> taxon name} and
+        * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
+        * 
+        * @param toName                  the taxon name of the target for this new name relationship
+        * @param type                    the type of this new name relationship
+        * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
+        * @see                                   #getRelationsToThisName()
+        * @see                                   #getNameRelations()
+        * @see                                   #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
+        * @see                                   #addNameRelationship(NameRelationship)
+        */
+public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
+               if (toName == null){
+                       throw new NullPointerException("Null is not allowed as name for a name relationship");
+               }
                NameRelationship rel = new NameRelationship(toName, this, type, citation, microCitation, ruleConsidered);
+//             if (type.isBasionymRelation() || type.isReplacedSynonymRelation()){
+//                     this.getHomotypicalGroup().merge(toName.getHomotypicalGroup());
+//             }
        }
        
        /**
@@ -352,16 +373,34 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
         * @param fromName                the taxon name of the source for this new name relationship
         * @param type                    the type of this new name relationship
         * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
+        * @param citation                the reference in which this relation was described
+        * @param microCitation   the reference detail for this relation (e.g. page) 
         * @see                                   #getRelationsFromThisName()
         * @see                                   #getNameRelations()
         * @see                                   #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
         * @see                                   #addNameRelationship(NameRelationship)
         */
        public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
-               NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
+               fromName.addRelationshipToName(this, type, null, null, ruleConsidered);
+//             NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
        }
+       /**
+        * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to <i>this</i> taxon name
+        * and adds it both to the set of {@link #getRelationsToThisName() relations to <i>this</i> taxon name} and
+        * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
+        * 
+        * @param fromName                the taxon name of the source for this new name relationship
+        * @param type                    the type of this new name relationship
+        * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
+        * @param citation                the reference in which this relation was described
+        * @param microCitation   the reference detail for this relation (e.g. page) 
+        * @see                                   #getRelationsFromThisName()
+        * @see                                   #getNameRelations()
+        * @see                                   #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
+        * @see                                   #addNameRelationship(NameRelationship)
+        */
        public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
-               NameRelationship rel = new NameRelationship(this, fromName, type, citation, microCitation, ruleConsidered);
+               fromName.addRelationshipToName(this, type, citation, microCitation, ruleConsidered);
        }
 
        /**
@@ -382,7 +421,7 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
                }else if(rel!=null && rel.getFromName().equals(this)){
                        this.relationsFromThisName.add(rel);                    
                }else{
-                       //TODO: raise error???
+                       throw new RuntimeException("NameRelationship is either null or the relationship does not reference this name");
                }
        }
        /** 
@@ -456,17 +495,15 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
        public void addRelationship(RelationshipBase relation) {
                if (relation instanceof NameRelationship){
                        addNameRelationship((NameRelationship)relation);
-                       if (relation.getType() != null && 
-                                               ( relation.getType().equals(NameRelationshipType.BASIONYM()) ||
-                                                 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM()) 
-                                                )){
+                       NameRelationshipType type = (NameRelationshipType)relation.getType();
+                       if (type != null && ( type.isBasionymRelation() || type.isReplacedSynonymRelation() ) ){
                                TaxonNameBase fromName = ((NameRelationship)relation).getFromName();
                                TaxonNameBase toName = ((NameRelationship)relation).getToName();
                                fromName.getHomotypicalGroup().merge(toName.getHomotypicalGroup());
                        }               
                }else{
                        logger.warn("Relationship not of type NameRelationship!");
-                       //TODO exception handling
+                       throw new IllegalArgumentException("Relationship not of type NameRelationship");
                }
        }
 
@@ -600,6 +637,25 @@ public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INam
                }
        }
        
+       /**
+        * Assigns a taxon name as {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym} of <i>this</i> taxon name
+        * and keeps the nomenclatural rule considered for it. The replaced synonym
+        * {@link NameRelationship relationship} will be added to <i>this</i> taxon name and to the replaced synonym.
+        * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the replaced synonym
+        * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
+        * 
+        * @param  basionym                     the taxon name to be set as the basionym of <i>this</i> taxon name
+        * @param  ruleConsidered       the string identifying the nomenclatural rule
+        * @see                                         #getBasionym()
+        * @see                                         #addBasionym(TaxonNameBase)
+        */
+       //TODO: Check if true: The replaced synonym cannot have itself a replaced synonym (?).
+       public void addReplacedSynonym(T replacedSynonym, ReferenceBase citation, String microcitation, String ruleConsidered){
+               if (replacedSynonym != null){
+                       replacedSynonym.addRelationshipToName(this, NameRelationshipType.REPLACED_SYNONYM(), citation, microcitation, ruleConsidered);
+               }
+       }
+       
        /** 
         * Removes the {@link NameRelationshipType#BASIONYM() basionym} {@link NameRelationship relationship} from the set of
         * {@link #getRelationsToThisName() name relationships to} <i>this</i> taxon name. The same relationhip will be
diff --git a/cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/HomotypicalGroupTest.java b/cdmlib-model/src/test/java/eu/etaxonomy/cdm/model/name/HomotypicalGroupTest.java
new file mode 100644 (file)
index 0000000..22ab1d1
--- /dev/null
@@ -0,0 +1,115 @@
+// $Id$\r
+/**\r
+* Copyright (C) 2007 EDIT\r
+* European Distributed Institute of Taxonomy \r
+* http://www.e-taxonomy.eu\r
+* \r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/\r
+\r
+package eu.etaxonomy.cdm.model.name;\r
+\r
+\r
+import java.util.Set;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.junit.After;\r
+import org.junit.AfterClass;\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.BeforeClass;\r
+import org.junit.Test;\r
+\r
+import eu.etaxonomy.cdm.model.common.DefaultTermInitializer;\r
+\r
+\r
+/**\r
+ * @author a.mueller\r
+ * @created 18.06.2009\r
+ * @version 1.0\r
+ */\r
+public class HomotypicalGroupTest {\r
+       private static final Logger logger = Logger.getLogger(HomotypicalGroupTest.class);\r
+\r
+       private static HomotypicalGroup group1;\r
+       private static HomotypicalGroup group2;\r
+       private static TaxonNameBase name1;\r
+       private static TaxonNameBase name2;\r
+       private static TaxonNameBase name3;\r
+       private static TaxonNameBase name4;\r
+       \r
+       \r
+       /**\r
+        * @throws java.lang.Exception\r
+        */\r
+       @BeforeClass\r
+       public static void setUpBeforeClass() throws Exception {\r
+               new DefaultTermInitializer().initialize();\r
+       }\r
+\r
+       /**\r
+        * @throws java.lang.Exception\r
+        */\r
+       @AfterClass\r
+       public static void tearDownAfterClass() throws Exception {\r
+       }\r
+\r
+       /**\r
+        * @throws java.lang.Exception\r
+        */\r
+       @Before\r
+       public void setUp() throws Exception {\r
+               name1 = BotanicalName.NewInstance(Rank.SPECIES());\r
+               name2 = BotanicalName.NewInstance(Rank.GENUS());\r
+               name3 = BotanicalName.NewInstance(Rank.SUBSPECIES());\r
+               name4 = BotanicalName.NewInstance(Rank.VARIETY());\r
+       }\r
+\r
+       /**\r
+        * @throws java.lang.Exception\r
+        */\r
+       @After\r
+       public void tearDown() throws Exception {\r
+       }\r
+       \r
+//*********************** TESTS ***********************************************/\r
+       \r
+       @Test\r
+       public void testGetBasionyms() {\r
+               name1.addBasionym(name2);\r
+               Set<TaxonNameBase> basionyms =  name1.getHomotypicalGroup().getBasionyms();\r
+               Assert.assertNotNull("Basionym set should not be null", basionyms);\r
+               Assert.assertEquals("Number of basionyms should be 1", 1, basionyms.size());\r
+               name3.addBasionym(name2);\r
+               basionyms =  name2.getHomotypicalGroup().getBasionyms();\r
+               Assert.assertEquals("Number of basionyms should be 1", 1, basionyms.size());\r
+               Assert.assertEquals("", name2, basionyms.iterator().next());\r
+               name3.addBasionym(name4);\r
+               basionyms =  name2.getHomotypicalGroup().getBasionyms();\r
+               Assert.assertEquals("Number of basionyms should be 2", 2, basionyms.size());\r
+//             Assert.assertEquals("", name2, basionyms.iterator().next());\r
+               \r
+       }\r
+       \r
+       @Test\r
+       public void testGetReplacedSynonym() {\r
+               name3.addReplacedSynonym(name4, null, null, null);\r
+               Set<TaxonNameBase> replacedSyn =  name3.getHomotypicalGroup().getReplacedSynonym();\r
+               Assert.assertNotNull("Replaced synonym set should not be null", replacedSyn);\r
+               Assert.assertEquals("Number of replaced synonym should be 1", 1, replacedSyn.size());\r
+       }\r
+       \r
+       @Test\r
+       public void testGetBasionymAndReplacedSynonymRelations(){\r
+               name1.addBasionym(name2);\r
+               name3.addBasionym(name2);\r
+               name4.addReplacedSynonym(name2, null, null, null);\r
+               Set<NameRelationship> rels = name2.getHomotypicalGroup().getBasionymAndReplacedSynonymRelations();\r
+               Assert.assertEquals("Number of relations should be 3", 3, rels.size());\r
+               \r
+       }\r
+       \r
+       \r
+       \r
+}\r