serial Version ID for HomGroup
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / HybridRelationship.java
index 05c6d1204a0eb90be775504d1e4e4d32a4ead9ba..c4cc412f051a9b427ed19bd47fe0b1e1c9e3531c 100644 (file)
 
 package eu.etaxonomy.cdm.model.name;
 
-import eu.etaxonomy.cdm.model.common.RelationshipBase;
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.ManyToOne;
+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.XmlIDREF;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
 import org.apache.log4j.Logger;
-import javax.persistence.*;
+import org.hibernate.annotations.Cascade;
+import org.hibernate.annotations.CascadeType;
+import org.hibernate.envers.Audited;
+
+import eu.etaxonomy.cdm.model.common.RelationshipBase;
+import eu.etaxonomy.cdm.model.reference.Reference;
 
 /**
- * http://rs.tdwg.org/ontology/voc/TaxonName.rdf#NomenclaturalNote
+ * The class representing a hybrid relationship between one of the {@link BotanicalName parents}
+ * of a hybrid taxon name and the hybrid taxon name itself. A hybrid taxon name
+ * is a {@link BotanicalName botanical taxon name} assigned to a hybrid plant following
+ * the {@link NomenclaturalCode#ICBN() ICBN} (Appendix I). A hybrid taxon name must have one 
+ * of the hybrid flags set. The hybrid relationship includes a {@link HybridRelationshipType hybrid relationship type}
+ * (for instance "first parent" or "female parent") and the article of the ICBN
+ * on which the hybrid taxon name relies.
+ * <P>
+ * This class corresponds partially to: <ul>
+ * <li> Relationship according to the TDWG ontology
+ * <li> TaxonRelationship according to the TCS
+ * </ul>
+ * 
  * @author m.doering
  * @version 1.0
  * @created 08-Nov-2007 13:06:26
  */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "HybridRelationship", propOrder = {
+       "relatedFrom",
+       "relatedTo",
+       "type",
+    "ruleConsidered"
+})
 @Entity
-public class HybridRelationship extends RelationshipBase<BotanicalName, BotanicalName, HybridRelationshipType> {
+@Audited
+public class HybridRelationship extends RelationshipBase<NonViralName, NonViralName, HybridRelationshipType>  implements Cloneable, Comparable<HybridRelationship>{
        private static final Logger logger = Logger.getLogger(HybridRelationship.class);
+       
        //The nomenclatural code rule considered. The article/note/recommendation in the code in question that is commented on in
        //the note property.
+       @XmlElement(name = "RuleConsidered")
        private String ruleConsidered;
+       
+       @XmlElement(name = "RelatedFrom")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch=FetchType.LAZY)
+    @Cascade(CascadeType.SAVE_UPDATE)
+       private NonViralName relatedFrom;
+
+       @XmlElement(name = "RelatedTo")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch=FetchType.LAZY)
+    @Cascade(CascadeType.SAVE_UPDATE)
+       private NonViralName relatedTo;
+       
+    @XmlElement(name = "Type")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch=FetchType.LAZY)
+       private HybridRelationshipType type;
 
-       //for hibernate, don't use
-       @Deprecated
+       /**
+        * @deprecated for hibernate use only, don't use
+        */
+       @Deprecated 
        private HybridRelationship(){
                super();
        }
 
        
+       // ************* CONSTRUCTORS *************/    
        /**
-        * creates a relationship between 2 names and adds this relationship object to the respective name relation sets
-        * @param toName
-        * @param fromName
-        * @param type
-        * @param ruleConsidered
+        * Class constructor: creates a new hybrid relationship instance with no
+        * reference and adds it to the respective
+        * {@link BotanicalName#getHybridRelationships() botanical taxon name relation sets} of both involved names.
+        * 
+        * @param toName                        the taxon name to be set as target for the new hybrid relationship
+        * @param fromName                      the taxon name to be set as source for the new hybrid relationship
+        * @param type                          the relationship type to be assigned to the new hybrid relationship
+        * @param ruleConsidered        the string indicating the article of the ICBN for the hybrid taxon name
+        * @see                                         #HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, Reference, String, String)
+        * @see                                         BotanicalName#addHybridRelationship(HybridRelationship)
         */
-       protected HybridRelationship(BotanicalName hybridName, BotanicalName parentName, HybridRelationshipType type, String ruleConsidered) {
-               this(parentName, hybridName, type, null, null, ruleConsidered);
+       protected HybridRelationship(NonViralName hybridName, NonViralName parentName, HybridRelationshipType type, String ruleConsidered) {
+               this(hybridName, parentName, type, null, null, ruleConsidered);
        }
        
        /**
-        * Constructor that adds immediately a relationship instance to both 
-        * Creates a relationship between 2 names and adds this relationship object to the respective name relation sets
-        * @param toName
-        * @param fromName
-        * @param type
-        * @param citation
-        * @param citationMicroReference
-        * @param ruleConsidered
+        * Class constructor: creates a new hybrid relationship instance including
+        * its {@link eu.etaxonomy.cdm.model.reference.Reference reference source} and adds it to the respective 
+        *{@link BotanicalName#getHybridRelationships() botanical taxon name relation sets} of both involved names.
+        * 
+        * @param toName                                the taxon name to be set as target for the new hybrid relationship
+        * @param fromName                              the taxon name to be set as source for the new hybrid relationship
+        * @param type                                  the relationship type to be assigned to the new hybrid relationship
+        * @param citation                              the reference source for the new hybrid relationship
+        * @param citationMicroReference        the string with the details describing the exact localisation within the reference
+        * @param ruleConsidered                the string indicating the article of the ICBN for the hybrid taxon name
+        * @see                                                 #HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, String)
+        * @see                                                 BotanicalName#addHybridRelationship(HybridRelationship)
         */
-       protected HybridRelationship(BotanicalName  hybridName, BotanicalName parentName, HybridRelationshipType type, ReferenceBase citation, String citationMicroReference, String ruleConsidered) {
+       protected HybridRelationship(NonViralName  hybridName, NonViralName parentName, HybridRelationshipType type, Reference citation, String citationMicroReference, String ruleConsidered) {
                super(parentName, hybridName, type, citation, citationMicroReference);
                this.setRuleConsidered(ruleConsidered);
        }       
        
-       public BotanicalName getParentName(){
-               return super.getRelatedFrom();
+       //********* METHODS **************************************/
+
+       /** 
+        * Returns the {@link BotanicalName botanical taxon name} that plays the parent role
+        * in <i>this</i> hybrid relationship.
+        *  
+        * @see   #getHybridName()
+        * @see   eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedFrom()
+        */
+       @Transient
+       public NonViralName getParentName(){
+               return this.getRelatedFrom();
        }
-       public void setParentName(BotanicalName parentName){
-               super.setRelatedFrom(parentName);
+       /**
+        * @see  #getParentName()
+        */
+       public void setParentName(NonViralName parentName){
+               this.setRelatedFrom(parentName);
        }
 
-       public BotanicalName getHybridName(){
-               return super.getRelatedTo();
+       /** 
+        * Returns the {@link BotanicalName botanical taxon name} that plays the child role
+        * (the child is actually the hybrid taxon name) in <i>this</i> hybrid relationship.
+        *  
+        * @see   #getParentName()
+        * @see   eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedTo()
+        */
+       @Transient
+       public NonViralName getHybridName(){
+               return this.getRelatedTo();
        }
-       public void setHybridName(BotanicalName hybridName){
-               super.setRelatedTo(hybridName);
+       /**
+        * @see  #getHybridName()
+        */
+       public void setHybridName(NonViralName hybridName){
+               this.setRelatedTo(hybridName);
        }
 
+       /** 
+        * Returns the ICBN rule considered (that is the
+        * article/note/recommendation in the nomenclatural code) for building
+        * the string representing the (child) hybrid {@link BotanicalName taxon name}
+        * within <i>this</i> hybrid relationship.
+        */
        public String getRuleConsidered(){
                return this.ruleConsidered;
        }
+       /**
+        * @see  #getRuleConsidered()
+        */
        public void setRuleConsidered(String ruleConsidered){
                this.ruleConsidered = ruleConsidered;
        }
 
+       protected NonViralName getRelatedFrom() {
+               return relatedFrom;
+       }
+
+       protected NonViralName getRelatedTo() {
+               return relatedTo;
+       }
+
+       public HybridRelationshipType getType() {
+               return type;
+       }
+
+       protected void setRelatedFrom(NonViralName relatedFrom) {
+               if (relatedFrom == null){
+                       this.deletedObjects.add(this.relatedFrom);
+               }
+               this.relatedFrom = relatedFrom;
+       }
+
+       protected void setRelatedTo(NonViralName relatedTo) {
+               if (relatedTo == null){
+                       this.deletedObjects.add(this.relatedTo);
+               }
+               this.relatedTo = relatedTo;
+       }
+
+       public void setType(HybridRelationshipType type) {
+               this.type = type;
+       }
+       
+// ************************ compareTo *************************************************
+       /* (non-Javadoc)
+        * @see java.lang.Comparable#compareTo(java.lang.Object)
+        */
+//     @Override  //leads to compile errors in some environments
+       public int compareTo(HybridRelationship rel2) {
+               HybridRelationshipType type1 = this.getType();
+               HybridRelationshipType type2 = rel2.getType();
+               int compareType = type1.compareTo(type2);
+               if (compareType != 0){
+                       return compareType;
+               }else{
+                       NonViralName related1 = this.getRelatedFrom();
+                       NonViralName<?> related2 = rel2.getRelatedFrom();
+                       if (related1 != related2){
+                               related1 = this.getRelatedTo();
+                               related2 = rel2.getRelatedTo();
+                       }
+                       String title1 = related1.getTitleCache();
+                       String title2 = related2.getTitleCache();
+                       return title1.compareTo(title2);
+               }
+       }
+       
+       
+//*********************** CLONE ********************************************************/
+       
+       /** 
+        * Clones <i>this</i> hybrid relationship. This is a shortcut that enables to create
+        * a new instance that differs only slightly from <i>this</i> hybrid relationship by
+        * modifying only some of the attributes.<BR>
+        * CAUTION: Cloning a relationship will not add the relationship to the according 
+        * {@link #relatedFrom} and {@link #relatedTo} objects. The method is meant to be used
+        * mainly for internal purposes (e.g. used within {@link TaxonNameBase#clone()}
+        * 
+        * @see eu.etaxonomy.cdm.model.common.RelationshipBase#clone()
+        * @see java.lang.Object#clone()
+        */
+       @Override
+       public Object clone() {
+               HybridRelationship result;
+               try {
+                       result = (HybridRelationship)super.clone();
+                       //no changes to: relatedFrom, relatedTo, type
+                       return result;
+               } catch (CloneNotSupportedException e) {
+                       logger.warn("Object does not implement cloneable");
+                       e.printStackTrace();
+                       return null;
+               }
+       }
+       
 }
\ No newline at end of file