Added Cascade.MERGE for some, not all relationships where Cascade.SAVE_UPDATE exists...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / agent / Team.java
index 9bca36f726c45bdb0d78ba2b78402221cb8ab0d4..19e9728a702c202659b2e081f445732889e13331 100644 (file)
 
 package eu.etaxonomy.cdm.model.agent;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.ManyToMany;
+import javax.persistence.Transient;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlIDREF;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
 
-import eu.etaxonomy.cdm.model.common.Keyword;
-import eu.etaxonomy.cdm.model.common.VersionableEntity;
 import org.apache.log4j.Logger;
+import org.hibernate.annotations.Cascade;
+import org.hibernate.annotations.CascadeType;
+import org.hibernate.annotations.IndexColumn;
+import org.hibernate.envers.Audited;
+import org.hibernate.search.annotations.Indexed;
+import org.springframework.beans.factory.annotation.Configurable;
 
-import java.util.*;
-import javax.persistence.*;
+import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
 
 /**
- * A team exists for itself or is built with the list of (distinct) persons
- * who belong to it.
- * In the first case the inherited attribute {@link common.IdentifiableEntity#titleCache titleCache} is to be used.
- * In the second case at least all abbreviated names (the attributes Person.titleCache)
+ * This class represents teams of {@link Person persons}. A team exists either for itself
+ * or is built with the list of (distinct) persons who belong to it.
+ * In the first case the inherited attribute {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} is to be used.
+ * In the second case at least all abbreviated names
+ * (the inherited attributes {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle})
  * or all full names (the strings returned by Person.generateTitle)
- * of the persons must exist. A team is an ordered set of persons.
+ * of the persons must exist. A team is a {@link java.util.List list} of persons.
+ * <P>
+ * This class corresponds to: <ul>
+ * <li> Team according to the TDWG ontology
+ * <li> AgentNames (partially) according to the TCS
+ * <li> MicroAgent (partially) according to the ABCD schema
+ * </ul>
  * 
  * @author m.doering
  * @version 1.0
  * @created 08-Nov-2007 13:06:58
  */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "Team", propOrder = {
+       "protectedNomenclaturalTitleCache",
+    "teamMembers"
+})
+@XmlRootElement
 @Entity
-public class Team extends Agent {
-       static Logger logger = Logger.getLogger(Team.class);
+@Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
+@Audited
+@Configurable
+public class Team extends TeamOrPersonBase<Team> {
+       private static final long serialVersionUID = 97640416905934622L;
+       public static final Logger logger = Logger.getLogger(Team.class);
+       
+    @XmlElement(name = "ProtectedNomenclaturalTitleCache")
+       private boolean protectedNomenclaturalTitleCache;
 
        //An abreviated name for the team (e. g. in case of nomenclatural authorteams). A non abreviated name for the team (e. g.
        //in case of some bibliographical references)
-       private List<Person> teamMembers = new ArrayList();
+    @XmlElementWrapper(name = "TeamMembers")
+    @XmlElement(name = "TeamMember")
+    @XmlIDREF
+    @XmlSchemaType(name = "IDREF")
+    @IndexColumn(name="sortIndex", base = 0)
+       @ManyToMany(fetch = FetchType.LAZY)
+       @Cascade(CascadeType.SAVE_UPDATE)
+       private List<Person> teamMembers = new ArrayList<Person>();
+       
        
        /** 
-        * Class constructor
+        * Creates a new team instance without any concrete {@link Person members}.
+        */
+       static public Team NewInstance(){
+               return new Team();
+       }
+       
+       /** 
+        * Class constructor (including the cache strategy defined in
+        * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}).
         */
        public Team() {
                super();
-               // TODO Auto-generated constructor stub
+               this.cacheStrategy = TeamDefaultCacheStrategy.NewInstance();
        }
 
-       @ManyToMany
+       /** 
+        * Returns the list of {@link Person members} belonging to <i>this</i> team. 
+        * A person may be a member of several distinct teams. 
+        */
        public List<Person> getTeamMembers(){
                return this.teamMembers;
        }
-       protected void setTeamMembers(List<Person> teamMembers){
-               this.teamMembers = teamMembers;
-       }
+       
        /** 
-        * Adds a new person to this team at the end of the members' list. 
+        * Adds a new {@link Person person} to <i>this</i> team at the end of the members' list. 
         *
         * @param  person  the person who should be added to the other team members
+        * @see            #getTeamMembers()
         * @see                    Person
         */
        public void addTeamMember(Person person){
                this.teamMembers.add(person);
        }
+       
+       /** 
+        * Adds a new {@link Person person} to <i>this</i> team
+        * at the given index place of the members' list. If the person is already
+        * a member of the list he will be moved to the given index place. 
+        * The index must be a positive integer. If the index is bigger than
+        * the present number of members the person will be added at the end of the list.
+        *
+        * @param  person  the person who should be added to the other team members
+        * @param  index   the position at which the new person should be placed within the members' list
+        * @see            #getTeamMembers()
+        * @see                    Person
+        */
+       public void addTeamMember(Person person, int index){
+               // TODO is still not fully implemented (range for index!)
+               logger.warn("not yet fully implemented (range for index!)");
+               int oldIndex = teamMembers.indexOf(person);
+               if (oldIndex != -1 ){
+                       teamMembers.remove(person);
+               }
+               this.teamMembers.add(index, person);
+       }
+       
        /** 
-        * Removes one person from the list of members of this team.
+        * Removes one person from the list of members of <i>this</i> team.
         *
-        * @param  person  the person who should be deleted from this team
-        * @see            #addTeamMember(Person)
+        * @param  person  the person who should be deleted from <i>this</i> team
+        * @see            #getTeamMembers()
         */
        public void removeTeamMember(Person person){
                this.teamMembers.remove(person);
        }
 
+       /**
+        * Generates an identification string for <i>this</i> team according to the strategy
+        * defined in {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}. This string is built
+        * with the full names of all persons belonging to its (ordered) members' list.
+        * This method overrides {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() generateTitle}.
+        * The result might be kept as {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(String) titleCache} if the
+        * flag {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#protectedTitleCache protectedTitleCache} is not set.
+        * 
+        * @return  a string which identifies <i>this</i> team
+        */
+//     @Override
+//     public String generateTitle() {
+//             return cacheStrategy.getTitleCache(this);
+//     }
+       
+       
+       /**
+        * Generates or returns the {@link TeamOrPersonBase#getnomenclaturalTitle() nomenclatural identification} string for <i>this</i> team.
+        * This method overrides {@link TeamOrPersonBase#getNomenclaturalTitle() getNomenclaturalTitle}.
+        * This string is built with the {@link TeamOrPersonBase#getNomenclaturalTitle() abbreviated names}
+        * of all persons belonging to its (ordered) members' list if the flag
+        * {@link #protectedNomenclaturalTitleCache protectedNomenclaturalTitleCache} is not set.
+        * Otherwise this method returns the present nomenclatural abbreviation.
+        * In case the string is generated the cache strategy used is defined in
+        * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}.
+        * The result might be kept as nomenclatural abbreviation
+        * by using the {@link #setNomenclaturalTitle(String) setNomenclaturalTitle} method.
+        * 
+        * @return  a string which identifies <i>this</i> team for nomenclature
+        */
        @Override
+       @Transient
+       public String getNomenclaturalTitle() {
+               if (protectedNomenclaturalTitleCache == PROTECTED){
+                       return this.nomenclaturalTitle;
+               }
+               if (nomenclaturalTitle == null){
+                       this.nomenclaturalTitle = cacheStrategy.getNomenclaturalTitle(this);
+               }
+               return nomenclaturalTitle;      
+       }
+       
        /**
-        * Generates an identification string for this team.
-        * This string might be built with the full names or with the abbreviated names
-        * of all persons belonging to its (ordered) members' list.
-        * This method overrides {@link common.IdentifiableEntity#generateTitle() generateTitle}.
-        * The result might be kept as {@link common.IdentifiableEntity#setTitleCache(String) titleCache} if the
-        * flag {@link common.IdentifiableEntity#protectedTitleCache protectedTitleCache} is not set.
+        * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
+        * and protects it from overwriting.
+        * This method overrides {@link TeamOrPersonBase#setNomenclaturalTitle(String) setNomenclaturalTitle}.
         * 
-        * @return  the string which identifies this team
+        * @see  #getNomenclaturalTitle()
+        * @see  #setNomenclaturalTitle(String, boolean)
         */
-       public String generateTitle() {
-               // TODO Auto-generated method stub
-               return null;
+       @Override
+       public void setNomenclaturalTitle(String nomenclaturalTitle) {
+               setNomenclaturalTitle(nomenclaturalTitle, PROTECTED);
+               this.nomenclaturalTitle = nomenclaturalTitle;
        }
 
+       /**
+        * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
+        * and a protection flag status to this string.
+        * 
+        * @see  #getNomenclaturalTitle()
+        */
+       public void setNomenclaturalTitle(String nomenclaturalTitle, boolean protectedNomenclaturalTitleCache) {
+               this.nomenclaturalTitle = nomenclaturalTitle;
+               this.protectedNomenclaturalTitleCache = protectedNomenclaturalTitleCache;
+       }
 }
\ No newline at end of file