references and microreferences for name relations
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / TaxonNameBase.java
index 13611bd8c7b7c520c9b98180cfb8b04fa96bfdaf..035707ebb385047d627a779e3e249ee86d02d486 100644 (file)
@@ -9,54 +9,67 @@
 
 package eu.etaxonomy.cdm.model.name;
 
-import eu.etaxonomy.cdm.model.occurrence.Specimen;
-import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
-import eu.etaxonomy.cdm.model.reference.ReferenceBase;
-import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
-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.common.IParsable;
-import eu.etaxonomy.cdm.model.common.IRelated;
-import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
-import eu.etaxonomy.cdm.model.common.IReferencedEntity;
-import eu.etaxonomy.cdm.model.common.RelationshipBase;
-
-
-import org.apache.log4j.Logger;
-import org.hibernate.annotations.Cascade;
-import org.hibernate.annotations.CascadeType;
-import org.hibernate.annotations.Index;
-import org.hibernate.annotations.Table;
-import org.hibernate.annotations.Target;
-
-import eu.etaxonomy.cdm.strategy.cache.INameCacheStrategy;
-
-
-
 import java.lang.reflect.Method;
-import java.util.*;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
-import javax.persistence.*;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+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.XmlAnyElement;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlIDREF;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlTransient;
 import javax.xml.bind.annotation.XmlType;
 
+import org.apache.log4j.Logger;
+import org.hibernate.annotations.Cascade;
+import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.Index;
+import org.hibernate.annotations.Table;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Field;
+import org.springframework.util.ReflectionUtils;
+
+import eu.etaxonomy.cdm.model.common.IParsable;
+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.description.TaxonNameDescription;
+import eu.etaxonomy.cdm.model.occurrence.Specimen;
+import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
+import eu.etaxonomy.cdm.model.reference.ReferenceBase;
+import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
+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.strategy.cache.name.INameCacheStrategy;
+
 /**
  * The upmost (abstract) class for scientific taxon names regardless of any
- * particular nomenclature code. The scientific taxon name does not depend
+ * particular {@link NomenclaturalCode nomenclature code}. The scientific taxon name does not depend
  * on the use made of it in a publication or a treatment
- * ({@link taxon.TaxonBase taxon concept respectively potential taxon})
- * as an {@link taxon.Taxon "accepted" respectively "correct" (taxon) name}
- * or as a {@link taxon.Synonym synonym}.
+ * ({@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon concept respectively potential taxon})
+ * as an {@link eu.etaxonomy.cdm.model.taxon.Taxon "accepted" respectively "correct" (taxon) name}
+ * or as a {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
+ * <P>
+ * This class corresponds partially to: <ul>
+ * <li> TaxonName according to the TDWG ontology
+ * <li> ScientificName and CanonicalName according to the TCS
+ * <li> ScientificName according to the ABCD schema
+ * </ul>
  * 
  * @author m.doering
  * @version 1.0
@@ -68,70 +81,114 @@ import javax.xml.bind.annotation.XmlType;
     "nomenclaturalMicroReference",
     "nomenclaturalReference",
     "rank",
+    "fullTitleCache",
+    "protectedFullTitleCache",
     "homotypicalGroup",
-    "nameTypeDesignations",
-    "specimenTypeDesignations",
+    "typeDesignations",
     "relationsFromThisName",
     "relationsToThisName",
     "status",
-    "taxonBases",
+    "descriptions",
+    "taxonBases"
 })
+@XmlRootElement(name = "TaxonNameBase")
 @Entity
+@Audited
 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
 @Table(appliesTo="TaxonNameBase", indexes = { @Index(name = "taxonNameBaseTitleCacheIndex", columnNames = { "titleCache" }) })
-public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCacheStrategy> extends IdentifiableEntity<TaxonNameBase> implements IReferencedEntity, IParsable, IRelated {
+public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INameCacheStrategy> extends IdentifiableEntity<S> implements IReferencedEntity, IParsable, IRelated {
 
-       static Logger logger = Logger.getLogger(TaxonNameBase.class);
+       private static final long serialVersionUID = -4530368639601532116L;
+       private static final Logger logger = Logger.getLogger(TaxonNameBase.class);
 
+       @XmlElement(name = "FullTitleCache")
+       @Column(length=330, name="fullTitleCache")
+       private String fullTitleCache;
+       
+       //if true titleCache will not be automatically generated/updated
+       @XmlElement(name = "ProtectedFullTitleCache")
+       private boolean protectedFullTitleCache;
+       
+    @XmlElementWrapper(name = "Descriptions")
+    @XmlElement(name = "Description")
+    @OneToMany(mappedBy="taxonName", fetch= FetchType.LAZY) 
+       @Cascade({CascadeType.SAVE_UPDATE})
+       private Set<TaxonNameDescription> descriptions = new HashSet<TaxonNameDescription>();
+       
     @XmlElement(name = "AppendedPhrase")
+    @Field(index= org.hibernate.search.annotations.Index.TOKENIZED)
        private String appendedPhrase;
        
     @XmlElement(name = "NomenclaturalMicroReference")
+    @Field(index= org.hibernate.search.annotations.Index.TOKENIZED)
        private String nomenclaturalMicroReference;
        
     @XmlAttribute
        private boolean hasProblem = false;
        
-    @XmlElementWrapper(name = "NameTypeDesignations")
-    @XmlElement(name = "NameTypeDesignation")
-    protected Set<NameTypeDesignation> nameTypeDesignations  = new HashSet<NameTypeDesignation>();
-       
-    @XmlElementWrapper(name = "SpecimenTypeDesignations")
-    @XmlElement(name = "SpecimenTypeDesignation")
-       private Set<SpecimenTypeDesignation> specimenTypeDesignations = new HashSet<SpecimenTypeDesignation>();
+    @XmlAttribute
+    private int problemStarts = -1;
+    
+    @XmlAttribute
+    private int problemEnds = -1;
+    
+    @XmlElementWrapper(name = "TypeDesignations")
+    @XmlElement(name = "TypeDesignation")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToMany(fetch = FetchType.LAZY)
+       //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
+       @Cascade(CascadeType.SAVE_UPDATE)
+       private Set<TypeDesignationBase> typeDesignations = new HashSet<TypeDesignationBase>();
 
     @XmlElement(name = "HomotypicalGroup")
-       private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch = FetchType.LAZY)
+       @Cascade({CascadeType.SAVE_UPDATE})
+       private HomotypicalGroup homotypicalGroup;
 
     @XmlElementWrapper(name = "RelationsFromThisName")
     @XmlElement(name = "RelationFromThisName")
-    @XmlIDREF
+    @OneToMany(mappedBy="relatedFrom", fetch= FetchType.LAZY)
+       //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN}) => DELETE_ORPHAN does not work ( org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan": eu.etaxonomy.cdm.model.name.TaxonNameBase.relationsFromThisName)
+       @Cascade(CascadeType.SAVE_UPDATE)
        private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
 
     @XmlElementWrapper(name = "RelationsToThisName")
     @XmlElement(name = "RelationToThisName")
     @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @OneToMany(mappedBy="relatedTo", fetch= FetchType.LAZY)
+       //@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
+       @Cascade(CascadeType.SAVE_UPDATE)
        private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
 
-    @XmlElementWrapper(name = "Stati")
-    @XmlElement(name = "Status")
-    @XmlIDREF
+    @XmlElementWrapper(name = "NomenclaturalStatuses")
+    @XmlElement(name = "NomenclaturalStatus")
+    @OneToMany(fetch= FetchType.LAZY)
+       @Cascade({CascadeType.SAVE_UPDATE})
        private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
 
     @XmlElementWrapper(name = "TaxonBases")
     @XmlElement(name = "TaxonBase")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @OneToMany(mappedBy="name", fetch= FetchType.LAZY)
        private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
-
+    
     @XmlElement(name = "Rank")
        @XmlIDREF
        @XmlSchemaType(name = "IDREF")
+       @ManyToOne(fetch = FetchType.EAGER)
        private Rank rank;
 
-//  TODO: This must be an IDREF to the corresponding nomenclatural reference.
-    @XmlAnyElement
-       private INomenclaturalReference nomenclaturalReference;
-
-       static Method methodTaxonBaseSetName;
+       @XmlElement(name = "NomenclaturalReference")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @ManyToOne(fetch = FetchType.LAZY)
+       @Cascade({CascadeType.SAVE_UPDATE})
+       private ReferenceBase nomenclaturalReference;
        
 // ************* CONSTRUCTORS *************/   
        /** 
@@ -142,45 +199,46 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         * @see #TaxonNameBase(Rank, HomotypicalGroup)
         */
        public TaxonNameBase() {
-               this(null, null);
+               super();
        }
        /** 
         * Class constructor: creates a new taxon name
-        * only containing its {@link common.Rank rank}.
+        * only containing its {@link Rank rank}.
         * 
-        * @param  rank  the rank to be assigned to this taxon name
-        * @see    #TaxonNameBase()
-        * @see    #TaxonNameBase(HomotypicalGroup)
-        * @see    #TaxonNameBase(Rank, HomotypicalGroup)
+        * @param  rank  the rank to be assigned to <i>this</i> taxon name
+        * @see                  #TaxonNameBase()
+        * @see                  #TaxonNameBase(HomotypicalGroup)
+        * @see                  #TaxonNameBase(Rank, HomotypicalGroup)
         */
        public TaxonNameBase(Rank rank) {
                this(rank, null);
        }
        /** 
         * Class constructor: creates a new taxon name
-        * only containing its {@link common.HomotypicalGroup homotypical group}.
+        * only containing its {@link HomotypicalGroup homotypical group}.
         * The new taxon name will be also added to the set of taxon names
-        * belonging to this homotypical group. If the homotypical group 
-        * does not exist a new instance will be created for it.
+        * belonging to this homotypical group.
         * 
-        * @param  homotypicalGroup  the homotypical group to which this taxon name belongs
-        * @see    #TaxonNameBase()
-        * @see    #TaxonNameBase(Rank)
-        * @see    #TaxonNameBase(Rank, HomotypicalGroup)
+        * @param  homotypicalGroup  the homotypical group to which <i>this</i> taxon name belongs
+        * @see                                          #TaxonNameBase()
+        * @see                                          #TaxonNameBase(Rank)
+        * @see                                          #TaxonNameBase(Rank, HomotypicalGroup)
         */
        public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
                this(null, homotypicalGroup);
        }
        /** 
         * Class constructor: creates a new taxon name
-        * only containing its {@link common.Rank rank} and
-        * its {@link common.HomotypicalGroup homotypical group}.
+        * only containing its {@link Rank rank} and
+        * its {@link HomotypicalGroup homotypical group}.
+        * The new taxon name will be also added to the set of taxon names
+        * belonging to this homotypical group.
         * 
-        * @param  rank  the rank to be assigned to this taxon name
-        * @param  homotypicalGroup  the homotypical group to which this taxon name belongs
-        * @see    #TaxonNameBase()
-        * @see    #TaxonNameBase(Rank)
-        * @see    #TaxonNameBase(HomotypicalGroup)
+        * @param  rank                          the rank to be assigned to <i>this</i> taxon name
+        * @param  homotypicalGroup  the homotypical group to which <i>this</i> taxon name belongs
+        * @see                                          #TaxonNameBase()
+        * @see                                          #TaxonNameBase(Rank)
+        * @see                                          #TaxonNameBase(HomotypicalGroup)
         */
        public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
                super();
@@ -192,14 +250,9 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
        
 //********* METHODS **************************************/
-
-       //@Index(name="TaxonNameBaseTitleCacheIndex")
-//     public String getTitleCache(){
-//             return super.getTitleCache();
-//     }
        
        /**
-        * Returns the boolean value "false" since the components of this taxon name
+        * Returns the boolean value "false" since the components of <i>this</i> taxon name
         * cannot follow the rules of a corresponding {@link NomenclaturalCode nomenclatural code}
         * which is not defined for this class. The nomenclature code depends on
         * the concrete name subclass ({@link BacterialName BacterialName},
@@ -212,10 +265,49 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        @Transient
        public abstract boolean isCodeCompliant();
        
+       public abstract String generateFullTitle();
 
+       @Transient
+       public String getFullTitleCache(){
+               if (protectedFullTitleCache){
+                       return this.fullTitleCache;                     
+               }
+               if (fullTitleCache == null){
+                       this.setFullTitleCache(generateFullTitle(), protectedFullTitleCache);
+               }
+               return fullTitleCache;
+       }
+       
+       @Transient
+       public List<Object> getTaggedName(){
+               return getCacheStrategy().getTaggedName(this);
+       }
+
+    public void setFullTitleCache(String fullTitleCache){
+               setFullTitleCache(fullTitleCache, PROTECTED);
+       }
+       
+       public void setFullTitleCache(String fullTitleCache, boolean protectCache){
+               //TODO truncation of full title cache
+               if (fullTitleCache != null && fullTitleCache.length() > 329){
+                       logger.warn("Truncation of full title cache: " + this.toString() + "/" + fullTitleCache);
+                       fullTitleCache = fullTitleCache.substring(0, 329) + "...";
+               }
+               this.fullTitleCache = fullTitleCache;
+               this.setProtectedFullTitleCache(protectCache);
+       }
+       
+       public boolean isProtectedFullTitleCache() {
+               return protectedFullTitleCache;
+       }
+
+       public void setProtectedFullTitleCache(boolean protectedFullTitleCache) {
+               this.protectedFullTitleCache = protectedFullTitleCache;
+       }
+       
        /** 
         * Returns the set of all {@link NameRelationship name relationships}
-        * in which this taxon name is involved. A taxon name can be both source
+        * in which <i>this</i> taxon name is involved. A taxon name can be both source
         * in some name relationships or target in some others.
         *  
         * @see    #getRelationsToThisName()
@@ -231,9 +323,10 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
                rels.addAll(getRelationsToThisName());
                return rels;
        }
+       
        /**
-        * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from this taxon name to another taxon name
-        * and adds it both to the set of {@link #getRelationsFromThisName() relations from this taxon name} and
+        * 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
@@ -247,9 +340,14 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
                NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
        }
+       
+       public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
+               NameRelationship rel = new NameRelationship(toName, this, type, citation, microCitation, ruleConsidered);
+       }
+       
        /**
-        * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to this taxon name
-        * and adds it both to the set of {@link #getRelationsToThisName() relations to this taxon name} and
+        * 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
@@ -263,14 +361,18 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
                NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
        }
+       public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
+               NameRelationship rel = new NameRelationship(this, fromName, type, citation, microCitation, ruleConsidered);
+       }
+
        /**
         * Adds an existing {@link NameRelationship name relationship} either to the set of
-        * {@link #getRelationsToThisName() relations to this taxon name} or to the set of
-        * {@link #getRelationsFromThisName() relations from this taxon name}. If neither the
-        * source nor the target of the name relationship match with this taxon
+        * {@link #getRelationsToThisName() relations to <i>this</i> taxon name} or to the set of
+        * {@link #getRelationsFromThisName() relations from <i>this</i> taxon name}. If neither the
+        * source nor the target of the name relationship match with <i>this</i> taxon name
         * no addition will be carried out.
         * 
-        * @param rel  the name relationship to be added to one of this taxon name's name relationships sets
+        * @param rel  the name relationship to be added to one of <i>this</i> taxon name's name relationships sets
         * @see            #getNameRelations()
         * @see            #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
         * @see            #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
@@ -286,17 +388,57 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
        /** 
         * Removes one {@link NameRelationship name relationship} from one of both sets of
-        * {@link #getNameRelations() name relationships} in which this taxon name is involved.
+        * {@link #getNameRelations() name relationships} in which <i>this</i> taxon name is involved.
         * The name relationship will also be removed from one of both sets belonging
         * to the second taxon name involved. Furthermore the fromName and toName
         * attributes of the name relationship object will be nullified. 
         *
         * @param  nameRelation  the name relationship which should be deleted from one of both sets
-        * @see    #getNameRelations()
+        * @see                                  #getNameRelations()
         */
        public void removeNameRelationship(NameRelationship nameRelation) {
-               //TODO to be implemented?
-               logger.warn("not yet fully implemented?");
+               
+               TaxonNameBase fromName = nameRelation.getFromName();
+               TaxonNameBase toName = nameRelation.getToName();
+
+               if (nameRelation != null) {
+                       nameRelation.setToName(null);
+                       nameRelation.setFromName(null);
+               }
+               
+               if (fromName != null) {
+                       fromName.removeNameRelationship(nameRelation);
+               }
+               
+               if (toName != null) {
+                       toName.removeNameRelationship(nameRelation);
+               }
+               
+               this.relationsToThisName.remove(nameRelation);
+               this.relationsFromThisName.remove(nameRelation);
+       }
+               
+       public void removeTaxonName(TaxonNameBase taxonName) {
+               Set<NameRelationship> nameRelationships = new HashSet<NameRelationship>();
+//             nameRelationships.addAll(this.getNameRelations());
+               nameRelationships.addAll(this.getRelationsFromThisName());
+               nameRelationships.addAll(this.getRelationsToThisName());
+               for(NameRelationship nameRelationship : nameRelationships) {
+                       // remove name relationship from this side 
+                       if (nameRelationship.getFromName().equals(this) && nameRelationship.getToName().equals(taxonName)) {
+                               this.removeNameRelation(nameRelationship);
+                       }
+               }
+       }
+       
+       public void removeNameRelation(NameRelationship nameRelation) {
+               nameRelation.setToName(null);
+       
+               TaxonNameBase name = nameRelation.getFromName();
+               if (name != null){
+                       nameRelation.setFromName(null);
+                       name.removeNameRelation(nameRelation);
+               }
                this.relationsToThisName.remove(nameRelation);
                this.relationsFromThisName.remove(nameRelation);
        }
@@ -306,18 +448,19 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         * Does exactly the same as the addNameRelationship method provided that
         * the given relationship is a name relationship.
         * 
-        * @param relation  the relationship to be added to one of this taxon name's name relationships sets
+        * @param relation  the relationship to be added to one of <i>this</i> taxon name's name relationships sets
         * @see                         #addNameRelationship(NameRelationship)
         * @see                         #getNameRelations()
         * @see                         NameRelationship
-        * @see                         common.RelationshipBase
+        * @see                         eu.etaxonomy.cdm.model.common.RelationshipBase
         */
        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() )){
+                                               ( relation.getType().equals(NameRelationshipType.BASIONYM()) ||
+                                                 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM()) 
+                                                )){
                                TaxonNameBase fromName = ((NameRelationship)relation).getFromName();
                                TaxonNameBase toName = ((NameRelationship)relation).getToName();
                                fromName.getHomotypicalGroup().merge(toName.getHomotypicalGroup());
@@ -331,62 +474,44 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        
        /** 
         * Returns the set of all {@link NameRelationship name relationships}
-        * in which this taxon name is involved as a source.
+        * in which <i>this</i> taxon name is involved as a source.
         *  
         * @see    #getNameRelations()
         * @see    #getRelationsToThisName()
         * @see    #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
         */
-       @OneToMany(mappedBy="relatedFrom", fetch= FetchType.LAZY)
-       @Cascade({CascadeType.SAVE_UPDATE})
        public Set<NameRelationship> getRelationsFromThisName() {
                return relationsFromThisName;
        }
-       private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
-               this.relationsFromThisName = relationsFromThisName;
-       }
-       
+
        /** 
         * Returns the set of all {@link NameRelationship name relationships}
-        * in which this taxon name is involved as a target.
+        * in which <i>this</i> taxon name is involved as a target.
         *  
         * @see    #getNameRelations()
         * @see    #getRelationsFromThisName()
         * @see    #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
         */
-       @OneToMany(mappedBy="relatedTo", fetch= FetchType.LAZY)
-       @Cascade({CascadeType.SAVE_UPDATE})
        public Set<NameRelationship> getRelationsToThisName() {
                return relationsToThisName;
        }
-       private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
-               this.relationsToThisName = relationsToThisName;
-       }
-
        
        /** 
         * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
-        * to this taxon name according to its corresponding nomenclature code.
+        * to <i>this</i> taxon name according to its corresponding nomenclature code.
         * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
         * and the nomenclatural code rule considered.
         *
         * @see     NomenclaturalStatus
         * @see     NomenclaturalStatusType
         */
-       @OneToMany(fetch= FetchType.LAZY)
-       @Cascade({CascadeType.SAVE_UPDATE})
        public Set<NomenclaturalStatus> getStatus() {
                return status;
        }
-       /** 
-        * @see     #getStatus()
-        */
-       protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
-               this.status = nomStatus;
-       }
+
        /** 
         * Adds a new {@link NomenclaturalStatus nomenclatural status}
-        * to this taxon name's set of nomenclatural status.
+        * to <i>this</i> taxon name's set of nomenclatural status.
         *
         * @param  nomStatus  the nomenclatural status to be added
         * @see                           #getStatus()
@@ -394,12 +519,13 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        public void addStatus(NomenclaturalStatus nomStatus) {
                this.status.add(nomStatus);
        }
+       
        /** 
-        * Removes one element from the set of nomenclatural status of this taxon name.
+        * Removes one element from the set of nomenclatural status of <i>this</i> taxon name.
         * Type and ruleConsidered attributes of the nomenclatural status object
         * will be nullified.
         *
-        * @param  nomStatus  the nomenclatural status of this taxon name which should be deleted
+        * @param  nomStatus  the nomenclatural status of <i>this</i> taxon name which should be deleted
         * @see                   #getStatus()
         */
        public void removeStatus(NomenclaturalStatus nomStatus) {
@@ -410,11 +536,11 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
 
        
        /**
-        * Indicates whether this taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
-        * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
-        * of any other taxon name. Returns true, if a basionym or a replaced synonym 
-        * relationship from this taxon name to another taxon name exists,
-        * false otherwise (also in case this taxon name is the only one in the
+        * Indicates whether <i>this</i> taxon name is a {@link NameRelationshipType#BASIONYM() basionym}
+        * or a {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym}
+        * of any other taxon name. Returns "true", if a basionym or a replaced 
+        * synonym {@link NameRelationship relationship} from <i>this</i> taxon name to another taxon name exists,
+        * false otherwise (also in case <i>this</i> taxon name is the only one in the
         * homotypical group).
         */
        @Transient
@@ -430,11 +556,11 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
        
        /**
-        * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
+        * Returns the taxon name which is the {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
         * The basionym of a taxon name is its epithet-bringing synonym.
-        * For instance Pinus abies L. was published by Linnaeus and the botanist
-        * Karsten transferred later this taxon to the genus Picea. Therefore,
-        * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
+        * For instance <i>Pinus abies</i> L. was published by Linnaeus and the botanist
+        * Karsten transferred later <i>this</i> taxon to the genus Picea. Therefore,
+        * <i>Pinus abies</i> L. is the basionym of the new combination <i>Picea abies</i> (L.) H. Karst.
         */
        @Transient
        public T getBasionym(){
@@ -443,52 +569,61 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
                return null;
        }
        /**
-        * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
-        * The basionym relationship will be added to this taxon name
+        * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
+        * The basionym {@link NameRelationship relationship} will be added to <i>this</i> taxon name
         * and to the basionym. The basionym cannot have itself a basionym.
-        * The homotypical group of this taxon name will be changed the basionyms homotypical group.
-        * @see  #getBasionym()
-        * @see  #addBasionym(TaxonNameBase, String)
+        * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
+        * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
+        * 
+        * @param  basionym             the taxon name to be set as the basionym of <i>this</i> taxon name
+        * @see                                 #getBasionym()
+        * @see                                 #addBasionym(TaxonNameBase, String)
         */
        public void addBasionym(T basionym){
-               addBasionym(basionym, null);
+               addBasionym(basionym, null, null, null);
        }
        /**
-        * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name
+        * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name
         * and keeps the nomenclatural rule considered for it. The basionym
-        * relationship will be added to this taxon name and to the basionym.
-        * The basionym cannot have itself as a basionym.
-        * The homotypical group of this taxon name will be changed the basionyms homotypical group.
-        * @see  #getBasionym()
-        * @see  #setBasionym(TaxonNameBase)
+        * {@link NameRelationship relationship} will be added to <i>this</i> taxon name and to the basionym.
+        * The basionym cannot have itself a basionym.
+        * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
+        * 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)
         */
-       public void addBasionym(T basionym, String ruleConsidered){
+       public void addBasionym(T basionym, ReferenceBase citation, String microcitation, String ruleConsidered){
                if (basionym != null){
-                       basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
+                       basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), 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
+        * removed from the set of {@link #getRelationsFromThisName() name relationships from} the taxon name
+        * previously used as basionym.
+        *
+        * @see   #getBasionym()
+        * @see   #addBasionym(TaxonNameBase)
+        */
        public void removeBasionym(){
                //TODO implement
                logger.warn("not yet implemented");
        }
-
-
-
-       @Transient
-       public abstract S getCacheStrategy();
-       public abstract void setCacheStrategy(S cacheStrategy);
        
        /** 
-        * Returns the taxonomic {@link Rank rank} of this taxon name.
+        * Returns the taxonomic {@link Rank rank} of <i>this</i> taxon name.
         *
         * @see         Rank
         */
-       @ManyToOne
-       //@Cascade({CascadeType.SAVE_UPDATE})
        public Rank getRank(){
                return this.rank;
        }
+       
        /**
         * @see  #getRank()
         */
@@ -497,39 +632,45 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
 
        /** 
-        * Returns the {@link reference.INomenclaturalReference nomenclatural reference} of this taxon name.
+        * Returns the {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} of <i>this</i> taxon name.
         * The nomenclatural reference is here meant to be the one publication
-        * this taxon name was originally published in while fulfilling the formal
-        * requirements as specified by the corresponding nomenclatural code.
+        * <i>this</i> taxon name was originally published in while fulfilling the formal
+        * requirements as specified by the corresponding {@link NomenclaturalCode nomenclatural code}.
         *
-        * @see         reference.INomenclaturalReference
-        * @see         reference.ReferenceBase
+        * @see         eu.etaxonomy.cdm.model.reference.INomenclaturalReference
+        * @see         eu.etaxonomy.cdm.model.reference.ReferenceBase
         */
-       @ManyToOne
-       @Cascade({CascadeType.SAVE_UPDATE})
-       @Target(ReferenceBase.class)
-       public INomenclaturalReference getNomenclaturalReference(){
-               return (INomenclaturalReference) this.nomenclaturalReference;
+       public ReferenceBase getNomenclaturalReference(){
+               return this.nomenclaturalReference;
        }
        /**
-        * Assigns a nomenclatural {@link reference.INomenclaturalReference nomenclatural reference} to this taxon name.
-        * The corresponding {@link reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
+        * Assigns a {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} to <i>this</i> taxon name.
+        * The corresponding {@link eu.etaxonomy.cdm.model.reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
         * as it is obviously used for nomenclatural purposes.
         *
+        * @throws IllegalArgumentException if parameter <code>nomenclaturalReference</code> is not assignable from {@link INomenclaturalReference}
         * @see  #getNomenclaturalReference()
         */
-       public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
-               this.nomenclaturalReference = nomenclaturalReference;
+       public void setNomenclaturalReference(ReferenceBase nomenclaturalReference){
+               if(nomenclaturalReference != null){
+                       if(!INomenclaturalReference.class.isAssignableFrom(nomenclaturalReference.getClass())){
+                               throw new IllegalArgumentException("Parameter nomenclaturalReference is not assignable from INomenclaturalReference");
+                       }
+                       this.nomenclaturalReference = (ReferenceBase)nomenclaturalReference;
+               } else {
+                       this.nomenclaturalReference = null;
+               }
        }
 
        /** 
-        * Returns the appended phrase string assigned to this taxon name.
+        * Returns the appended phrase string assigned to <i>this</i> taxon name.
         * The appended phrase is a non-atomised addition to a name. It is
         * not ruled by a nomenclatural code.
         */
        public String getAppendedPhrase(){
                return this.appendedPhrase;
        }
+       
        /**
         * @see  #getAppendedPhrase()
         */
@@ -538,8 +679,8 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
 
        /** 
-        * Returns the details string of the nomenclatural reference assigned
-        * to this taxon name. The details describe the exact localisation within
+        * Returns the details string of the {@link #getNomenclaturalReference() nomenclatural reference} assigned
+        * to <i>this</i> taxon name. The details describe the exact localisation within
         * the publication used as nomenclature reference. These are mostly
         * (implicitly) pages but can also be figures or tables or any other
         * element of a publication. A nomenclatural micro reference (details)
@@ -556,202 +697,242 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
                this.nomenclaturalMicroReference = nomenclaturalMicroReference;
        }
 
-       /**
-        * Returns the boolean value of the flag indicating whether the used {@link eu.etaxonomy.cdm.strategy.parser.INonViralNameParser parser} 
-        * method was able to parse the taxon name string successfully (false)
-        * or not (true). The parser itself may also depend on the {@link NomenclaturalCode nomenclatural code}
-        * governing the construction of this taxon name.
-        *  
-        * @return  the boolean value of the hasProblem flag
-        * @see     #getNameCache()
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#getHasProblem()
         */
        public boolean getHasProblem(){
                return this.hasProblem;
        }
-       /**
-        * @see  #getHasProblem()
+       
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#setHasProblem(boolean)
         */
        public void setHasProblem(boolean hasProblem){
                this.hasProblem = hasProblem;
        }
-       /**
-        * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.  
-        *  
-        * @see  #getHasProblem()
+       
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#hasProblem()
         */
        public boolean hasProblem(){
                return getHasProblem();
        }
-
-
-       /** 
-        * Returns the set of {@link NameTypeDesignation name type designations} assigned
-        * to this taxon name the rank of which must be above "species".
-        * The name type designations include all the taxon names used to typify
-        * this name and eventually the rejected or conserved status
-        * of these designations.
-        *
-        * @see     NameTypeDesignation
-        * @see     SpecimenTypeDesignation
+       
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#problemStarts()
         */
-       @OneToMany
-       //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
-       @Cascade(CascadeType.SAVE_UPDATE)
-       public Set<NameTypeDesignation> getNameTypeDesignations() {
-               return nameTypeDesignations;
+       public int getProblemStarts(){
+               return this.problemStarts;
        }
-       /** 
-        * @see     #getNameTypeDesignations()
+       
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemStarts(int)
         */
-       protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
-               this.nameTypeDesignations = nameTypeDesignations;
+       public void setProblemStarts(int start) {
+               this.problemStarts = start;
        }
-
        
-       /** 
-        * Creates and adds a new {@link NameTypeDesignation name type designation}
-        * to this taxon name's set of name type designations.
-        *
-        * @param  typeSpecies                          the taxon name to be used as type of this taxon name
-        * @param  citation                                     the reference for this new designation
-        * @param  citationMicroReference       the string with the details (generally pages) within the reference
-        * @param  originalNameString           the taxon name used in the reference to assert this designation
-        * @param  isRejectedType                       the boolean status for rejected
-        * @param  isConservedType                      the boolean status for conserved
-        * @see                                                         #getNameTypeDesignations()
-        * @see                                                         #addTypeDesignation(Specimen, TypeDesignationStatus, ReferenceBase, String, String)
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#problemEnds()
         */
-       public void addNameTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
-               NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
+       public int getProblemEnds(){
+               return this.problemEnds;
        }
-       
-       /** 
-        * Removes one element from the set of {@link NameTypeDesignation name type designations} of this taxon name.
-        * The name type designation itself will be nullified.
-        *
-        * @param  typeDesignation  the name type designation of this taxon name which should be deleted
-        * @see                                 #getNameTypeDesignations()
-        * @see                                 #removeTypeDesignation(SpecimenTypeDesignation)
+
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemEnds(int)
         */
-       public void removeNameTypeDesignation(NameTypeDesignation typeDesignation) {
-               //TODO
-               logger.warn("not yet fully implemented: nullify the name type designation itself?");
-               this.nameTypeDesignations.remove(typeDesignation);
+       public void setProblemEnds(int end) {
+               this.problemEnds = end;
        }
+
+//*********************** TYPE DESIGNATION *********************************************//     
        
-       /**
-        * @return the specimenTypeDesignations
+       /** 
+        * Returns the set of {@link TypeDesignationBase type designations} assigned
+        * to <i>this</i> taxon name.
+        * @see     NameTypeDesignation
+        * @see     SpecimenTypeDesignation
         */
-       @ManyToMany
-       @Cascade(CascadeType.SAVE_UPDATE)
-       public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
-               return specimenTypeDesignations;
+       public Set<TypeDesignationBase> getTypeDesignations() {
+               return typeDesignations;
        }
-       /**
-        * @param specimenTypeDesignations the specimenTypeDesignations to set
+       
+       /** 
+        * Removes one element from the set of {@link TypeDesignationBase type designations} assigned to
+        * <i>this</i> taxon name. The type designation itself will be nullified.
+        *
+        * @param  typeDesignation  the type designation which should be deleted
         */
-       protected void setSpecimenTypeDesignations(Set<SpecimenTypeDesignation> specimenTypeDesignations) {
-               this.specimenTypeDesignations = specimenTypeDesignations;
+       public void removeTypeDesignation(TypeDesignationBase typeDesignation) {
+               logger.warn("not yet fully implemented: nullify the specimen type designation itself?");
+               this.typeDesignations.remove(typeDesignation);
        }
        
        /** 
         * Returns the set of {@link SpecimenTypeDesignation specimen type designations} assigned
-        * indirectly to this taxon name through its {@link HomotypicalGroup homotypical group}.
-        * The rank of this taxon name is generally "species" or below.
-        * The specimen type designations include all the specimens on which
-        * the typification of this name is based (and which are common to all
-        * taxon names belonging to the homotypical group) and eventually
-        * the status of these designations.
+        * to <i>this</i> taxon name. The {@link Rank rank} of <i>this</i> taxon name is generally
+        * "species" or below. The specimen type designations include all the
+        * specimens on which the typification of this name is based (which are
+        * exclusively used to typify taxon names belonging to the same
+        * {@link HomotypicalGroup homotypical group} to which <i>this</i> taxon name
+        * belongs) and eventually the status of these designations.
         *
         * @see     SpecimenTypeDesignation
         * @see     NameTypeDesignation
+        * @see     HomotypicalGroup
         */
        @Transient
        public Set<SpecimenTypeDesignation> getSpecimenTypeDesignationsOfHomotypicalGroup() {
-               return this.getHomotypicalGroup().getTypeDesignations();
+               return this.getHomotypicalGroup().getSpecimenTypeDesignations();
        }
        
+//*********************** NAME TYPE DESIGNATION *********************************************//        
+       
        /** 
-        * Adds a new {@link SpecimenTypeDesignation specimen type designation}
-        * (using its attributes as parameters) to the set of specimen type designations assigned to the
-        * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
+        * Returns the set of {@link NameTypeDesignation name type designations} assigned
+        * to <i>this</i> taxon name the rank of which must be above "species".
+        * The name type designations include all the taxon names used to typify
+        * <i>this</i> taxon name and eventually the rejected or conserved status
+        * of these designations.
         *
-        * @param  typeSpecimen                         the specimen to be used as a type for this taxon name's homotypical group
-        * @param  status                                       the specimen type designation status
-        * @param  citation                                     the reference for this new specimen type designation
-        * @param  citationMicroReference       the string with the details (generally pages) within the reference
-        * @param  originalNameString           the taxon name used in the reference to assert this designation
-        * @see                                                         HomotypicalGroup#getTypeDesignations()
-        * @see                                                         #addTypeDesignation(TaxonNameBase, ReferenceBase, String, String, boolean, boolean)
-        * @see                                                         TypeDesignationStatus
+        * @see     NameTypeDesignation
+        * @see     SpecimenTypeDesignation
         */
-       public void addSpecimenTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean addToAllNames) {
-               SpecimenTypeDesignation specimenTypeDesignation = 
-                       SpecimenTypeDesignation.NewInstance(typeSpecimen, status, citation, citationMicroReference, originalNameString);
-               this.getHomotypicalGroup().addTypeDesignation(specimenTypeDesignation, addToAllNames);
+       @Transient
+       public Set<NameTypeDesignation> getNameTypeDesignations() {
+               Set<NameTypeDesignation> result = new HashSet<NameTypeDesignation>();
+               for (TypeDesignationBase typeDesignation : this.typeDesignations){
+                       if (typeDesignation instanceof NameTypeDesignation){
+                               result.add((NameTypeDesignation)typeDesignation);
+                       }
+               }
+               return result;
        }
-
-       //only to be used for xxx
+       
        /** 
-        * Adds a new {@link SpecimenTypeDesignation specimen type designation}
-        * to the set of specimen type designations assigned to the
-        * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
+        * Creates and adds a new {@link NameTypeDesignation name type designation}
+        * to <i>this</i> taxon name's set of type designations.
         *
-        * @param  specimenTypeDesignation      the specimen type designation to be added for this taxon name's homotypical group
-        * @see                                                         #addSpecimenTypeDesignation(Specimen, TypeDesignationStatus, ReferenceBase, String, String, boolean)
-        * @see                                                         HomotypicalGroup#getTypeDesignations()
-        * @see                                                         #addTypeDesignation(TaxonNameBase, ReferenceBase, String, String, boolean, boolean)
+        * @param  typeSpecies                          the taxon name to be used as type of <i>this</i> taxon name
+        * @param  citation                                     the reference for this new designation
+        * @param  citationMicroReference       the string with the details (generally pages) within the reference
+        * @param  originalNameString           the taxon name string used in the reference to assert this designation
+        * @param  isRejectedType                       the boolean status for a rejected name type designation
+        * @param  isConservedType                      the boolean status for a conserved name type designation
+        * @param  isLectoType                          the boolean status for a lectotype name type designation
+        * @param  isNotDesignated                      the boolean status for a name type designation without name type
+        * @param  addToAllHomotypicNames       the boolean indicating whether the name type designation should be
+        *                                                                      added to all taxon names of the homotypical group this taxon name belongs to
+        * @see                                                         #getNameTypeDesignations()
+        * @see                                                         NameTypeDesignation
+        * @see                                                         TypeDesignationBase#isNotDesignated()
         */
-       protected void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation) {
-               this.specimenTypeDesignations.add(specimenTypeDesignation);
+       public void addNameTypeDesignation(TaxonNameBase typeSpecies, 
+                               ReferenceBase citation, 
+                               String citationMicroReference, 
+                               String originalNameString, 
+                               boolean isRejectedType, 
+                               boolean isConservedType, 
+                               boolean isLectoType, 
+                               boolean isNotDesignated, 
+                               boolean addToAllHomotypicNames) {
+               NameTypeDesignation nameTypeDesignation = new NameTypeDesignation(typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType, isLectoType, isNotDesignated);
+               nameTypeDesignation.setLectoType(isLectoType);
+               addTypeDesignation(nameTypeDesignation, addToAllHomotypicNames);
        }
        
-       //only to be used for xxx
+//*********************** SPECIMEN TYPE DESIGNATION *********************************************//    
+       
        /** 
-        * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
-        * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
-        *
-        * @param  SpecimenTypeDesignation  the specimen type designation which should be deleted
-        * @see                                                 HomotypicalGroup#getTypeDesignations()
-        * @see                                                 #removeTypeDesignation(SpecimenTypeDesignation)
-        * @see                                 #removeNameTypeDesignation(NameTypeDesignation)
+        * Returns the set of {@link SpecimenTypeDesignation specimen type designations}
+        * that typify <i>this</i> taxon name.
         */
-       protected void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation) {
-               this.specimenTypeDesignations.remove(specimenTypeDesignation);
+       @Transient
+       public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
+               Set<SpecimenTypeDesignation> result = new HashSet<SpecimenTypeDesignation>();
+               for (TypeDesignationBase typeDesignation : this.typeDesignations){
+                       if (typeDesignation instanceof SpecimenTypeDesignation){
+                               result.add((SpecimenTypeDesignation)typeDesignation);
+                       }
+               }
+               return result;
        }
 
+       
        /** 
-        * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
-        * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
-        * The specimen type designation itself will be nullified.
+        * Creates and adds a new {@link SpecimenTypeDesignation specimen type designation}
+        * to <i>this</i> taxon name's set of type designations.
         *
-        * @param  typeDesignation  the specimen type designation which should be deleted
-        * @see                                 HomotypicalGroup#getTypeDesignations()
-        * @see                                 #removeSpecimenTypeDesignation(SpecimenTypeDesignation)
-        * @see                                 #removeNameTypeDesignation(NameTypeDesignation)
+        * @param  typeSpecimen                         the specimen to be used as a type for <i>this</i> taxon name
+        * @param  status                                       the specimen type designation status
+        * @param  citation                                     the reference for this new specimen type designation
+        * @param  citationMicroReference       the string with the details (generally pages) within the reference
+        * @param  originalNameString           the taxon name used in the reference to assert this designation
+        * @param  isNotDesignated                      the boolean status for a specimen type designation without specimen type
+        * @param  addToAllHomotypicNames       the boolean indicating whether the specimen type designation should be
+        *                                                                      added to all taxon names of the homotypical group the typified
+        *                                                                      taxon name belongs to
+        * @see                                                         #getSpecimenTypeDesignations()
+        * @see                                                         SpecimenTypeDesignationStatus
+        * @see                                                         SpecimenTypeDesignation
+        * @see                                                         TypeDesignationBase#isNotDesignated()
         */
-       public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
-               logger.warn("not yet fully implemented: nullify the specimen type designation itself?");
-               this.homotypicalGroup.removeTypeDesignation(typeDesignation);
+       public void addSpecimenTypeDesignation(Specimen typeSpecimen, 
+                               SpecimenTypeDesignationStatus status, 
+                               ReferenceBase citation, 
+                               String citationMicroReference, 
+                               String originalNameString, 
+                               boolean isNotDesignated, 
+                               boolean addToAllHomotypicNames) {
+               SpecimenTypeDesignation specimenTypeDesignation = new SpecimenTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString, isNotDesignated);
+               addTypeDesignation(specimenTypeDesignation, addToAllHomotypicNames);
        }
+       
+       private boolean addTypeDesignation(TypeDesignationBase typeDesignation, boolean addToAllNames){
+               //at them moment typeDesignations are not persisted with the homotypical group
+               //so explicit adding to the homotypical group is not necessary.
+               if (typeDesignation != null){
+                       this.typeDesignations.add(typeDesignation);
+                       typeDesignation.addTypifiedName(this);
+                       
+                       if (addToAllNames){
+                               for (TaxonNameBase taxonName : this.getHomotypicalGroup().getTypifiedNames()){
+                                       if (taxonName != this){
+                                               taxonName.addTypeDesignation(typeDesignation, false);
+                                       }
+                               }
+                       }
+               }
+               return true;
+       }
+       
 
+       
+//*********************** HOMOTYPICAL GROUP *********************************************//    
+
+       
        /** 
         * Returns the {@link HomotypicalGroup homotypical group} to which
-        * this taxon name belongs. A homotypical group represents all taxon names
-        * that share the same type specimens.
+        * <i>this</i> taxon name belongs. A homotypical group represents all taxon names
+        * that share the same types.
         *
         * @see         HomotypicalGroup
         */
-       @ManyToOne
-       @Cascade({CascadeType.SAVE_UPDATE})
+       
        public HomotypicalGroup getHomotypicalGroup() {
                return homotypicalGroup;
        }
-       @Deprecated //only for bidirectional and persistence use
-       protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
-               this.homotypicalGroup = newHomotypicalGroup;            
+       
+       /* 
+        * @see #getHomotypicalGroup()
+        */
+       protected void setHomotypicalGroup(HomotypicalGroup homotypicalGroup) {
+               this.homotypicalGroup = homotypicalGroup;
        }
 
+// *************************************************************************//
+       
        /** 
         * @see #getNomenclaturalReference()
         */
@@ -764,21 +945,25 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
 
        /** 
         * Returns the complete string containing the
-        * {@link reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
-        * (including {@link #getNomenclaturalMicroReference() details}) assigned to this taxon name.
+        * {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
+        * and the {@link #getNomenclaturalMicroReference() details} assigned to <i>this</i> taxon name.
         * 
-        * @return  the string containing the nomenclatural reference of this taxon name
-        * @see         reference.INomenclaturalReference#getNomenclaturalCitation()
+        * @return  the string containing the nomenclatural reference of <i>this</i> taxon name
+        * @see         eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation()
         * @see         #getNomenclaturalReference()
         * @see         #getNomenclaturalMicroReference()
         */
        @Transient
+       @Deprecated
        public String getCitationString(){
                logger.warn("getCitationString not yet implemented");
                return null;
        }
 
-       @Transient
+       /** 
+        * Not yet implemented
+        */
+       @Deprecated
        public String[] getProblems(){
                logger.warn("getProblems not yet implemented");
                return null;
@@ -786,11 +971,11 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
 
        /**
         * Returns the string containing the publication date (generally only year)
-        * of the nomenclatural reference for this taxon name, null if there is
+        * of the {@link #getNomenclaturalReference() nomenclatural reference} for <i>this</i> taxon name, null if there is
         * no nomenclatural reference.
         * 
-        * @return  the string containing the publication date of this taxon name
-        * @see         reference.INomenclaturalReference#getYear()
+        * @return  the string containing the publication date of <i>this</i> taxon name
+        * @see         eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getYear()
         */
        @Transient
        public String getReferenceYear(){
@@ -802,74 +987,55 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
 
        /** 
-        * Returns the set of {@link taxon.TaxonBase taxon bases} that refer to this taxon name.
+        * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
         * In this context a taxon base means the use of a taxon name by a reference
-        * either as a taxon ("accepted/correct" name) or as a (junior) synonym.
-        * A taxon name can be used by several distinct references but only once
+        * either as a {@link eu.etaxonomy.cdm.model.taxon.Taxon taxon} ("accepted/correct" name) or
+        * as a (junior) {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
+        * A taxon name can be used by several distinct {@link eu.etaxonomy.cdm.model.reference.ReferenceBase references} but only once
         * within a taxonomic treatment (identified by one reference).
         *
-        * @see taxon.TaxonBase
         * @see #getTaxa()
         * @see #getSynonyms()
         */
-       @OneToMany(mappedBy="name", fetch= FetchType.LAZY)
        public Set<TaxonBase> getTaxonBases() {
                return this.taxonBases;
        }
+       
        /** 
-        * @see     #getTaxonBases()
-        */
-       protected void setTaxonBases(Set<TaxonBase> taxonBases) {
-               if (taxonBases == null){
-                       taxonBases = new HashSet<TaxonBase>();
-               }else{
-                       this.taxonBases = taxonBases;
-               }
-       }
-       /** 
-        * Adds a new {@link taxon.TaxonBase taxon base}
-        * to the set of taxon bases using this taxon name.
+        * Adds a new {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon base}
+        * to the set of taxon bases using <i>this</i> taxon name.
         *
         * @param  taxonBase  the taxon base to be added
         * @see                           #getTaxonBases()
+        * @see                           #removeTaxonBase(TaxonBase)
         */
        //TODO protected
        public void addTaxonBase(TaxonBase taxonBase){
+               Method method = ReflectionUtils.findMethod(TaxonBase.class, "setName", new Class[] {TaxonNameBase.class});
+               ReflectionUtils.makeAccessible(method);
+               ReflectionUtils.invokeMethod(method, taxonBase, new Object[] {this});
                taxonBases.add(taxonBase);
-               initMethods();
-               invokeSetMethod(methodTaxonBaseSetName, taxonBase);
        }
        /** 
-        * Removes one element from the set of {@link taxon.TaxonBase taxon bases} that refer to this taxon name.
+        * Removes one element from the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
         *
         * @param  taxonBase    the taxon base which should be removed from the corresponding set
+        * @see                                 #getTaxonBases()
         * @see                                 #addTaxonBase(TaxonBase)
         */
        public void removeTaxonBase(TaxonBase taxonBase){
+               Method method = ReflectionUtils.findMethod(TaxonBase.class, "setName", new Class[] {TaxonNameBase.class});
+               ReflectionUtils.makeAccessible(method);
+               ReflectionUtils.invokeMethod(method, taxonBase, new Object[] {null});
                taxonBases.remove(taxonBase);
-               initMethods();
-               invokeSetMethodWithNull(methodTaxonBaseSetName, taxonBase);
-       }
-
-       private void initMethods(){
-               if (methodTaxonBaseSetName == null){
-                       try {
-                               methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
-                               methodTaxonBaseSetName.setAccessible(true);
-                       } catch (Exception e) {
-                               e.printStackTrace();
-                               //TODO handle exception
-                       }
-               }
        }
        
-       
        /**
-        * Returns the set of {@link taxon.Taxon taxa} ("accepted/correct" names according to any
-        * reference) that are based on this taxon name. This set is a subset of
+        * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Taxon taxa} ("accepted/correct" names according to any
+        * reference) that are based on <i>this</i> taxon name. This set is a subset of
         * the set returned by getTaxonBases(). 
         * 
-        * @see taxon.Taxon
+        * @see eu.etaxonomy.cdm.model.taxon.Taxon
         * @see #getTaxonBases()
         * @see #getSynonyms()
         */
@@ -885,11 +1051,11 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
        }
        
        /**
-        * Returns the set of {@link taxon.Synonym (junior) synonyms} (according to any
-        * reference) that are based on this taxon name. This set is a subset of
+        * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Synonym (junior) synonyms} (according to any
+        * reference) that are based on <i>this</i> taxon name. This set is a subset of
         * the set returned by getTaxonBases(). 
         * 
-        * @see taxon.Synonym
+        * @see eu.etaxonomy.cdm.model.taxon.Synonym
         * @see #getTaxonBases()
         * @see #getTaxa()
         */
@@ -904,10 +1070,60 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
                return result;
        }
        
+       
+// *********** DESCRIPTIONS *************************************      
+
+       /**
+        * Returns the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
+        * to <i>this</i> taxon name. A taxon name description is a piece of information
+        * concerning the taxon name like for instance the content of its first
+        * publication (protolog) or a picture of this publication.
+        * 
+        * @see #addDescription(TaxonNameDescription)
+        * @see #removeDescription(TaxonNameDescription)
+        * @see eu.etaxonomy.cdm.model.description.TaxonNameDescription
+        */
+       public Set<TaxonNameDescription> getDescriptions() {
+               return descriptions;
+       }
+
+       /** 
+        * Adds a new {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name description}
+        * to the set of taxon name descriptions assigned to <i>this</i> taxon name. The
+        * content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute} of the
+        * taxon name description itself will be replaced with <i>this</i> taxon name.
+        *
+        * @param  description  the taxon name description to be added
+        * @see                                 #getDescriptions()
+        * @see                                 #removeDescription(TaxonNameDescription)
+        */
+       public void addDescription(TaxonNameDescription description) {
+               java.lang.reflect.Field field = ReflectionUtils.findField(TaxonNameDescription.class, "taxonName", TaxonNameBase.class);
+               ReflectionUtils.makeAccessible(field);
+               ReflectionUtils.setField(field, description, this);
+               descriptions.add(description);
+       }
+       /** 
+        * Removes one element from the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
+        * to <i>this</i> taxon name. The content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute}
+        * of the description itself will be set to "null".
+        *
+        * @param  description  the taxon name description which should be removed
+        * @see                         #getDescriptions()
+        * @see                         #addDescription(TaxonNameDescription)
+        * @see                                 eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName()
+        */
+       public void removeDescription(TaxonNameDescription description) {
+               java.lang.reflect.Field field = ReflectionUtils.findField(TaxonNameDescription.class, "taxonName", TaxonNameBase.class);
+               ReflectionUtils.makeAccessible(field);
+               ReflectionUtils.setField(field, description, null);
+               descriptions.remove(description);
+       }
+       
 // ***********
        /**
         * Returns the boolean value indicating whether a given taxon name belongs
-        * to the same {@link HomotypicalGroup homotypical group} as this taxon name (true)
+        * to the same {@link HomotypicalGroup homotypical group} as <i>this</i> taxon name (true)
         * or not (false). Returns "true" only if the homotypical groups of both
         * taxon names exist and if they are identical. 
         *
@@ -915,6 +1131,7 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         * @return                         the boolean value of the check
         * @see                            HomotypicalGroup
         */
+       @Transient
        public boolean isHomotypic(TaxonNameBase homoTypicName) {
                if (homoTypicName == null) {
                        return false;
@@ -929,13 +1146,12 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
                return false;
        }
        
-       
-       
 //*********  Rank comparison shortcuts   ********************//
        /**
-        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of this
+        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
         * taxon name is higher than the genus rank (true) or not (false).
         * Suprageneric non viral names are monomials.
+        * Returns false if rank is null.
         * 
         * @see  #isGenus()
         * @see  #isInfraGeneric()
@@ -944,12 +1160,15 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         */
        @Transient
        public boolean isSupraGeneric() {
+               if (rank == null){
+                       return false;
+               }
                return getRank().isSupraGeneric();
        }
        /**
-        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of this
+        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
         * taxon name is the genus rank (true) or not (false). Non viral names with
-        * genus rank are monomials.
+        * genus rank are monomials. Returns false if rank is null.
         *
         * @see  #isSupraGeneric()
         * @see  #isInfraGeneric()
@@ -958,13 +1177,16 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         */
        @Transient
        public boolean isGenus() {
+               if (rank == null){
+                       return false;
+               }
                return getRank().isGenus();
        }
        /**
-        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of this
-        * taxon name is higher than the species aggregate rank and lower than
-        * the genus rank (true) or not (false). Infrageneric non viral names
-        * are binomials.
+        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
+        * taxon name is higher than the species rank and lower than the
+        * genus rank (true) or not (false). Infrageneric non viral names are
+        * binomials. Returns false if rank is null.
         *
         * @see  #isSupraGeneric()
         * @see  #isGenus()
@@ -973,13 +1195,16 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         */
        @Transient
        public boolean isInfraGeneric() {
+               if (rank == null){
+                       return false;
+               }
                return getRank().isInfraGeneric();
        }
        /**
-        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of this
-        * taxon name is the species or species aggregate rank (true) or not (false). Non viral names
+        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
+        * taxon name is the species rank (true) or not (false). Non viral names
         * with species rank are binomials.
-
+        * Returns false if rank is null.
         *
         * @see  #isSupraGeneric()
         * @see  #isGenus()
@@ -988,12 +1213,16 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         */
        @Transient
        public boolean isSpecies() {
+               if (rank == null){
+                       return false;
+               }
                return getRank().isSpecies();
        }
        /**
-        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of this
+        * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
         * taxon name is lower than the species rank (true) or not (false).
         * Infraspecific non viral names are trinomials.
+        * Returns false if rank is null.
         *
         * @see  #isSupraGeneric()
         * @see  #isGenus()
@@ -1002,13 +1231,16 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         */
        @Transient
        public boolean isInfraSpecific() {
+               if (rank == null){
+                       return false;
+               }
                return getRank().isInfraSpecific();
        }
        
        
        /**
         * Returns null as the {@link NomenclaturalCode nomenclatural code} that governs
-        * the construction of this taxon name since there is no specific
+        * the construction of <i>this</i> taxon name since there is no specific
         * nomenclatural code defined. The real implementention takes place in the
         * subclasses {@link ViralName ViralName}, {@link BacterialName BacterialName},
         * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName} and
@@ -1019,27 +1251,23 @@ public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCach
         * @see         #isCodeCompliant()
         * @see         #getHasProblem()
         */
-       @Transient
-       abstract public NomenclaturalCode getNomeclaturalCode();
+       abstract public NomenclaturalCode getNomenclaturalCode();
        /* (non-Javadoc)
         * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
         */
        /**
-        * Generates and returns the string with the scientific name of this
-        * taxon name.
-        * This string may be stored in the inherited
-        * {@link common.IdentifiableEntity#getTitleCache() titleCache} attribute.
+        * Generates and returns the string with the scientific name of <i>this</i>
+        * taxon name (only non viral taxon names can be generated from their
+        * components). This string may be stored in the inherited
+        * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
         * This method overrides the generic and inherited
-        * IdentifiableEntity#generateTitle() method.
+        * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() method} from
+        * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
         *
         * @return  the string with the composed name of this non viral taxon name with authorship (and maybe year)
-        * @see         common.IdentifiableEntity#generateTitle()
-        * @see         common.IdentifiableEntity#getTitleCache()
+        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
+        * @see         eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
         */
-       @Override
-       public String generateTitle() {
-               // TODO Auto-generated method stub
-               return null;
-       }
-       
-}
\ No newline at end of file
+//     @Override
+//     public abstract String generateTitle();
+}