commit after merge from trunc
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / BotanicalName.java
index aba9f9f83bdbc845ea6319166a25144014266478..9e635ebe3ac060f2377d6b3459421c4286106690 100644 (file)
 package eu.etaxonomy.cdm.model.name;
 
 
-import java.util.HashSet;
-import java.util.Set;
+import java.util.Map;
 
 import javax.persistence.Entity;
-import javax.persistence.OneToMany;
-import javax.persistence.Transient;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
 import org.apache.log4j.Logger;
-import org.hibernate.annotations.Cascade;
-import org.hibernate.annotations.CascadeType;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Indexed;
+import org.springframework.beans.factory.annotation.Configurable;
 
+import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
-import eu.etaxonomy.cdm.model.common.RelationshipBase;
+import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
 import eu.etaxonomy.cdm.strategy.cache.name.BotanicNameDefaultCacheStrategy;
 import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
@@ -45,42 +43,23 @@ import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "BotanicalName", propOrder = {
-    "isHybridFormula",
-    "isMonomHybrid",
-    "isBinomHybrid",
-    "isTrinomHybrid",
-    "isAnamorphic",
-    "hybridRelationships"
+    "anamorphic"
 })
 @XmlRootElement(name = "BotanicalName")
 @Entity
-public class BotanicalName extends NonViralName {
-       
+@Indexed(index = "eu.etaxonomy.cdm.model.name.TaxonNameBase")
+@Audited
+@Configurable
+public class BotanicalName extends NonViralName<BotanicalName> implements Cloneable /*, IMergable*/ {
+       private static final long serialVersionUID = 6818651572463497727L;
+       @SuppressWarnings("unused")
        private static final Logger logger = Logger.getLogger(BotanicalName.class);
        
-       //if set: this name is a hybrid formula (a hybrid that does not have an own name) and no other hybrid flags may be set. A
-       //hybrid name  may not have either an authorteam nor other name components.
-    @XmlElement(name ="IsHybridFormula")
-       private boolean isHybridFormula = false;
-       
-    @XmlElement(name ="IsMonomHybrid")
-       private boolean isMonomHybrid = false;
-       
-    @XmlElement(name ="IsBinomHybrid")
-       private boolean isBinomHybrid = false;
-       
-    @XmlElement(name ="IsTrinomHybrid")
-       private boolean isTrinomHybrid = false;
-       
        //Only for fungi: to indicate that the type of the name is asexual or not
     @XmlElement(name ="IsAnamorphic")
-       private boolean isAnamorphic;
-       
-    @XmlElementWrapper(name = "HybridRelationships")
-    @XmlElement(name = "HybridRelationship")
-       private Set<HybridRelationship> hybridRelationships = new HashSet();
+       private boolean anamorphic;
 
-       static private INonViralNameParser nameParser = new NonViralNameParserImpl();
+       static private INonViralNameParser<?> nameParser = new NonViralNameParserImpl();
        
        // ************* CONSTRUCTORS *************/    
        //needed by hibernate
@@ -248,7 +227,7 @@ public class BotanicalName extends NonViralName {
                if (nameParser == null){
                        nameParser = new NonViralNameParserImpl();
                }
-               return (BotanicalName)nameParser.parseFullName(fullNameString, NomenclaturalCode.ICBN(),  rank);
+               return (BotanicalName)nameParser.parseFullName(fullNameString, NomenclaturalCode.ICNAFP,  rank);
        }
        
        /**
@@ -282,256 +261,22 @@ public class BotanicalName extends NonViralName {
                if (nameParser == null){
                        nameParser = new NonViralNameParserImpl();
                }
-               return (BotanicalName)nameParser.parseReferencedName(fullNameAndReferenceString, NomenclaturalCode.ICBN(), rank);
-       }
-       
-       
-       /** 
-        * Returns the set of all {@link HybridRelationship hybrid relationships}
-        * in which <i>this</i> botanical taxon name is involved. Any botanical taxon name
-        * (even itself a hybrid taxon name) can be a parent of another hybrid
-        * taxon name.
-        *  
-        * @see    #getParentRelationships()
-        * @see    #getChildRelationships()
-        * @see    #addHybridRelationship(HybridRelationship)
-        * @see    #addRelationship(RelationshipBase)
-        */
-       @OneToMany
-       @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
-       public Set<HybridRelationship> getHybridRelationships() {
-               return hybridRelationships;
-       }
-       /**
-        * @see  #getHybridRelationships()
-        */
-       protected void setHybridRelationships(Set<HybridRelationship> relationships) {
-               this.hybridRelationships = relationships;
-       }
-       /**
-        * Adds the given {@link HybridRelationship hybrid relationship} to the set
-        * of {@link #getHybridRelationships() hybrid relationships} of both botanical taxon names
-        * involved in this hybrid relationship. One of both botanical taxon names
-        * must be <i>this</i> botanical taxon name otherwise no addition will be carried
-        * out. The {@link eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedTo() child botanical taxon name}
-        * must be a hybrid, which means that one of its four hybrid flags must be set.
-        * 
-        * @param relationship  the hybrid relationship to be added
-        * @see                                 #isHybridFormula()
-        * @see                                 #isMonomHybrid()
-        * @see                                 #isBinomHybrid()
-        * @see                                 #isTrinomHybrid()
-        * @see                                 #getHybridRelationships()
-        * @see                                 #getParentRelationships()
-        * @see                                 #getChildRelationships()
-        * @see                                 #addRelationship(RelationshipBase)
-        */
-       protected void addHybridRelationship(HybridRelationship relationship) {
-               this.hybridRelationships.add(relationship);
-       }
-       
-       /**
-        * Creates a new {@link HybridRelationship#HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, String) hybrid relationship} 
-        * to <i>this</i> botanical name. A HybridRelationship may be of type
-        * "is first/second parent" or "is male/female parent". By invoking this
-        * method <i>this</i> botanical name becomes a hybrid child of the parent
-        * botanical name.
-        * 
-        * @param parentName      the botanical name of the parent for this new hybrid 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                                   #addHybridChild(BotanicalName, HybridRelationshipType,String )
-        * @see                                   #getRelationsToThisName()
-        * @see                                   #getNameRelations()
-        * @see                                   #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
-        * @see                                   #addNameRelationship(NameRelationship)
-        */
-       public void addHybridParent(BotanicalName parentName, HybridRelationshipType type, String ruleConsidered){
-               HybridRelationship rel = new HybridRelationship(this, parentName, type, ruleConsidered);
-       }
-       
-       /**
-        * Creates a new {@link HybridRelationship#HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, String) hybrid relationship} 
-        * to <i>this</i> botanical name. A HybridRelationship may be of type
-        * "is first/second parent" or "is male/female parent". By invoking this
-        * method <i>this</i> botanical name becomes a parent of the hybrid child
-        * botanical name.
-        * 
-        * @param childName               the botanical name of the child for this new hybrid 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                                   #addHybridParent(BotanicalName, HybridRelationshipType,String )
-        * @see                                   #getRelationsToThisName()
-        * @see                                   #getNameRelations()
-        * @see                                   #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
-        * @see                                   #addNameRelationship(NameRelationship)
-        */
-       public void addHybridChild(BotanicalName childName, HybridRelationshipType type, String ruleConsidered){
-               HybridRelationship rel = new HybridRelationship(childName, this, type, ruleConsidered);
-       }
-       
-       
-       /** 
-        * Removes one {@link HybridRelationship hybrid relationship} from the set of
-        * {@link #getHybridRelationships() hybrid relationships} in which <i>this</i> botanical taxon name
-        * is involved. The hybrid relationship will also be removed from the set
-        * belonging to the second botanical taxon name involved. 
-        *
-        * @param  relationship  the hybrid relationship which should be deleted from the corresponding sets
-        * @see                                  #getHybridRelationships()
-        */
-       public void removeHybridRelationship(HybridRelationship relationship) {
-               //TODO
-               logger.warn("Birelationship not yet implemented");
-               this.hybridRelationships.remove(relationship);
+               return (BotanicalName)nameParser.parseReferencedName(fullNameAndReferenceString, NomenclaturalCode.ICNAFP, rank);
        }
 
-       /** 
-        * Returns the set of all {@link HybridRelationship hybrid relationships}
-        * in which <i>this</i> botanical taxon name is involved as a {@link common.RelationshipBase#getRelatedFrom() parent}.
-        *  
-        * @see    #getHybridRelationships()
-        * @see    #getChildRelationships()
-        * @see    HybridRelationshipType
-        */
-       @Transient
-       public Set<HybridRelationship> getParentRelationships() {
-               // FIXME: filter relations
-               return hybridRelationships;
-       }
-       /** 
-        * Returns the set of all {@link HybridRelationship hybrid relationships}
-        * in which <i>this</i> botanical taxon name is involved as a {@link common.RelationshipBase#getRelatedTo() child}.
-        *  
-        * @see    #getHybridRelationships()
-        * @see    #getParentRelationships()
-        * @see    HybridRelationshipType
-        */
-       @Transient
-       public Set<HybridRelationship> getChildRelationships() {
-               // FIXME: filter relations
-               return hybridRelationships;
-       }
+//***********************      
 
-       /**
-        * Does the same as the addHybridRelationship method if the given
-        * {@link common.RelationshipBase relation} is also a {@link HybridRelationship hybrid relationship}.
-        * Otherwise this method does the same as the overwritten {@link TaxonNameBase#addRelationship(RelationshipBase) addRelationship}
-        * method from TaxonNameBase.
-        * 
-        * @param relation  the relationship to be added to some of <i>this</i> taxon name's relationships sets
-        * @see                         #addHybridRelationship(HybridRelationship)
-        * @see                         TaxonNameBase#addRelationship(RelationshipBase)
-        * @see                         TaxonNameBase#addNameRelationship(NameRelationship)
-        */
+       private static Map<String, java.lang.reflect.Field> allFields = null;
        @Override
-       @Deprecated  //To be used by RelationshipBase only
-       public void addRelationship(RelationshipBase relation) {
-               if (relation instanceof HybridRelationship){
-                       addHybridRelationship((HybridRelationship)relation);
-               }else {
-                       super.addRelationship(relation);
+    protected Map<String, java.lang.reflect.Field> getAllFields(){
+       if (allFields == null){
+                       allFields = CdmUtils.getAllFields(this.getClass(), CdmBase.class, false, false, false, true);
                }
-       }
-
-       /**
-        * Returns the boolean value of the flag indicating whether the name of <i>this</i>
-        * botanical taxon name is a hybrid formula (true) or not (false). A hybrid
-        * named by a hybrid formula (composed with its parent names by placing the
-        * multiplication sign between them) does not have an own published name
-        * and therefore has neither an {@link NonViralName#getAuthorshipCache() autorship}
-        * nor other name components. If this flag is set no other hybrid flags may
-        * be set.
-        *  
-        * @return  the boolean value of the isHybridFormula flag
-        * @see         #isMonomHybrid()
-        * @see         #isBinomHybrid()
-        * @see         #isTrinomHybrid()
-        */
-       public boolean isHybridFormula(){
-               return this.isHybridFormula;
-       }
-
-       /**
-        * @see  #isHybridFormula()
-        */
-       public void setHybridFormula(boolean isHybridFormula){
-               this.isHybridFormula = isHybridFormula;
-       }
-
-       /**
-        * Returns the boolean value of the flag indicating whether <i>this</i> botanical
-        * taxon name is the name of an intergeneric hybrid (true) or not (false).
-        * In this case the multiplication sign is placed before the scientific
-        * name. If this flag is set no other hybrid flags may be set.
-        *  
-        * @return  the boolean value of the isMonomHybrid flag
-        * @see         #isHybridFormula()
-        * @see         #isBinomHybrid()
-        * @see         #isTrinomHybrid()
-        */
-       public boolean isMonomHybrid(){
-               return this.isMonomHybrid;
-       }
-
-       /**
-        * @see  #isMonomHybrid()
-        * @see  #isBinomHybrid()
-        * @see  #isTrinomHybrid()
-        */
-       public void setMonomHybrid(boolean isMonomHybrid){
-               this.isMonomHybrid = isMonomHybrid;
-       }
-
-       /**
-        * Returns the boolean value of the flag indicating whether <i>this</i> botanical
-        * taxon name is the name of an interspecific hybrid (true) or not (false).
-        * In this case the multiplication sign is placed before the species
-        * epithet. If this flag is set no other hybrid flags may be set.
-        *  
-        * @return  the boolean value of the isBinomHybrid flag
-        * @see         #isHybridFormula()
-        * @see         #isMonomHybrid()
-        * @see         #isTrinomHybrid()
-        */
-       public boolean isBinomHybrid(){
-               return this.isBinomHybrid;
-       }
-
-       /**
-        * @see  #isBinomHybrid()
-        * @see  #isMonomHybrid()
-        * @see  #isTrinomHybrid()
-        */
-       public void setBinomHybrid(boolean isBinomHybrid){
-               this.isBinomHybrid = isBinomHybrid;
-       }
-
-       /**
-        * Returns the boolean value of the flag indicating whether <i>this</i> botanical
-        * taxon name is the name of an infraspecific hybrid (true) or not (false).
-        * In this case the term "notho-" (optionally abbreviated "n-") is used as
-        * a prefix to the term denoting the infraspecific rank of <i>this</i> botanical
-        * taxon name. If this flag is set no other hybrid flags may be set.
-        *  
-        * @return  the boolean value of the isTrinomHybrid flag
-        * @see         #isHybridFormula()
-        * @see         #isMonomHybrid()
-        * @see         #isBinomHybrid()
-        */
-       public boolean isTrinomHybrid(){
-               return this.isTrinomHybrid;
-       }
-
-       /**
-        * @see  #isTrinomHybrid()
-        * @see  #isBinomHybrid()
-        * @see  #isMonomHybrid()
-        */
-       public void setTrinomHybrid(boolean isTrinomHybrid){
-               this.isTrinomHybrid = isTrinomHybrid;
-       }
+       return allFields;
+    }
 
+//************************* 
+       
        /**
         * Returns the boolean value of the flag indicating whether the specimen
         * type of <i>this</i> botanical taxon name for a fungus is asexual (true) or not
@@ -542,14 +287,14 @@ public class BotanicalName extends NonViralName {
         * @return  the boolean value of the isAnamorphic flag
         */
        public boolean isAnamorphic(){
-               return this.isAnamorphic;
+               return this.anamorphic;
        }
 
        /**
         * @see  #isAnamorphic()
         */
-       public void setAnamorphic(boolean isAnamorphic){
-               this.isAnamorphic = isAnamorphic;
+       public void setAnamorphic(boolean anamorphic){
+               this.anamorphic = anamorphic;
        }
        
        
@@ -563,11 +308,44 @@ public class BotanicalName extends NonViralName {
         * @see         NonViralName#isCodeCompliant()
         * @see         TaxonNameBase#getHasProblem()
         */
-       @Transient
        @Override
        public NomenclaturalCode getNomenclaturalCode(){
-               return NomenclaturalCode.ICBN();
+               return NomenclaturalCode.ICNAFP;
+       }
 
+       
+       /**
+        * Checks if this name is an autonym.<BR>
+        * An autonym is a taxon name that has equal specific and infra specific epithets.<BR>
+        * {@link http://ibot.sav.sk/icbn/frameset/0010Ch2Sec1a006.htm#6.8. Vienna Code ยง6.8}
+        * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
+        */
+       @Override
+       public boolean isAutonym(){
+               if (this.getRank() != null && this.getSpecificEpithet() != null && this.getInfraSpecificEpithet() != null && 
+                               this.getRank().isInfraSpecific() && this.getSpecificEpithet().trim().equals(this.getInfraSpecificEpithet().trim())){
+                       return true;
+               }else{
+                       return false;
+               }
+       }
+       
+//*********************** CLONE ********************************************************/
+       
+       /** 
+        * Clones <i>this</i> botanical name. This is a shortcut that enables to create
+        * a new instance that differs only slightly from <i>this</i> botanical name by
+        * modifying only some of the attributes.
+        * 
+        * @see eu.etaxonomy.cdm.model.name.NonViralName#clone()
+        * @see java.lang.Object#clone()
+        */
+       @Override
+       public Object clone() {
+               BotanicalName result = (BotanicalName)super.clone();
+               //no changes to: title, authorTeam, hasProblem, nomenclaturallyRelevant, uri
+               return result;
        }
 
+
 }
\ No newline at end of file