Agent cache strategies
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / agent / Team.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.agent;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import javax.persistence.Entity;
16 import javax.persistence.FetchType;
17 import javax.persistence.ManyToMany;
18 import javax.persistence.Transient;
19 import javax.xml.bind.annotation.XmlAccessType;
20 import javax.xml.bind.annotation.XmlAccessorType;
21 import javax.xml.bind.annotation.XmlElement;
22 import javax.xml.bind.annotation.XmlElementWrapper;
23 import javax.xml.bind.annotation.XmlIDREF;
24 import javax.xml.bind.annotation.XmlRootElement;
25 import javax.xml.bind.annotation.XmlSchemaType;
26 import javax.xml.bind.annotation.XmlType;
27
28 import org.apache.log4j.Logger;
29 import org.hibernate.annotations.Cascade;
30 import org.hibernate.annotations.CascadeType;
31 import org.hibernate.annotations.IndexColumn;
32 import org.hibernate.envers.Audited;
33 import org.hibernate.search.annotations.Indexed;
34 import org.springframework.beans.factory.annotation.Configurable;
35
36 import eu.etaxonomy.cdm.common.CdmUtils;
37 import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
38 import eu.etaxonomy.cdm.strategy.match.IMatchable;
39 import eu.etaxonomy.cdm.strategy.match.MatchMode;
40 import eu.etaxonomy.cdm.strategy.match.Match;
41 import eu.etaxonomy.cdm.strategy.merge.IMergable;
42
43 /**
44 * This class represents teams of {@link Person persons}. A team exists either for itself
45 * or is built with the list of (distinct) persons who belong to it.
46 * In the first case the inherited attribute {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} is to be used.
47 * In the second case at least all abbreviated names
48 * (the inherited attributes {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle})
49 * or all full names (the strings returned by Person.generateTitle)
50 * of the persons must exist. A team is a {@link java.util.List list} of persons.
51 * <P>
52 * This class corresponds to: <ul>
53 * <li> Team according to the TDWG ontology
54 * <li> AgentNames (partially) according to the TCS
55 * <li> MicroAgent (partially) according to the ABCD schema
56 * </ul>
57 *
58 * @author m.doering
59 * @version 1.0
60 * @created 08-Nov-2007 13:06:58
61 */
62 @XmlAccessorType(XmlAccessType.FIELD)
63 @XmlType(name = "Team", propOrder = {
64 "protectedNomenclaturalTitleCache",
65 "teamMembers"
66 })
67 @XmlRootElement
68 @Entity
69 @Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
70 @Audited
71 @Configurable
72 public class Team extends TeamOrPersonBase<Team> {
73 private static final long serialVersionUID = 97640416905934622L;
74 public static final Logger logger = Logger.getLogger(Team.class);
75
76 @XmlElement(name = "ProtectedNomenclaturalTitleCache")
77 private boolean protectedNomenclaturalTitleCache;
78
79 //An abreviated name for the team (e. g. in case of nomenclatural authorteams). A non abreviated name for the team (e. g.
80 //in case of some bibliographical references)
81 @XmlElementWrapper(name = "TeamMembers")
82 @XmlElement(name = "TeamMember")
83 @XmlIDREF
84 @XmlSchemaType(name = "IDREF")
85 @IndexColumn(name="sortIndex", base = 0)
86 @ManyToMany(fetch = FetchType.LAZY)
87 @Cascade(CascadeType.SAVE_UPDATE)
88 @Match(MatchMode.MATCH)
89 private List<Person> teamMembers = new ArrayList<Person>();
90
91
92 /**
93 * Creates a new team instance without any concrete {@link Person members}.
94 */
95 static public Team NewInstance(){
96 return new Team();
97 }
98
99 /**
100 * Class constructor (including the cache strategy defined in
101 * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}).
102 */
103 public Team() {
104 super();
105 this.cacheStrategy = TeamDefaultCacheStrategy.NewInstance();
106 }
107
108 /**
109 * Returns the list of {@link Person members} belonging to <i>this</i> team.
110 * A person may be a member of several distinct teams.
111 */
112 public List<Person> getTeamMembers(){
113 return this.teamMembers;
114 }
115
116 /**
117 * Adds a new {@link Person person} to <i>this</i> team at the end of the members' list.
118 *
119 * @param person the person who should be added to the other team members
120 * @see #getTeamMembers()
121 * @see Person
122 */
123 public void addTeamMember(Person person){
124 this.teamMembers.add(person);
125 }
126
127 /**
128 * Adds a new {@link Person person} to <i>this</i> team
129 * at the given index place of the members' list. If the person is already
130 * a member of the list he will be moved to the given index place.
131 * The index must be a positive integer. If the index is bigger than
132 * the present number of members the person will be added at the end of the list.
133 *
134 * @param person the person who should be added to the other team members
135 * @param index the position at which the new person should be placed within the members' list
136 * @see #getTeamMembers()
137 * @see Person
138 */
139 public void addTeamMember(Person person, int index){
140 // TODO is still not fully implemented (range for index!)
141 logger.warn("not yet fully implemented (range for index!)");
142 int oldIndex = teamMembers.indexOf(person);
143 if (oldIndex != -1 ){
144 teamMembers.remove(person);
145 }
146 this.teamMembers.add(index, person);
147 }
148
149 /**
150 * Removes one person from the list of members of <i>this</i> team.
151 *
152 * @param person the person who should be deleted from <i>this</i> team
153 * @see #getTeamMembers()
154 */
155 public void removeTeamMember(Person person){
156 this.teamMembers.remove(person);
157 }
158
159 /**
160 * Generates an identification string for <i>this</i> team according to the strategy
161 * defined in {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}. This string is built
162 * with the full names of all persons belonging to its (ordered) members' list.
163 * This method overrides {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() generateTitle}.
164 * The result might be kept as {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(String) titleCache} if the
165 * flag {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#protectedTitleCache protectedTitleCache} is not set.
166 *
167 * @return a string which identifies <i>this</i> team
168 */
169 // @Override
170 // public String generateTitle() {
171 // return cacheStrategy.getTitleCache(this);
172 // }
173
174
175 /**
176 * Generates or returns the {@link TeamOrPersonBase#getnomenclaturalTitle() nomenclatural identification} string for <i>this</i> team.
177 * This method overrides {@link TeamOrPersonBase#getNomenclaturalTitle() getNomenclaturalTitle}.
178 * This string is built with the {@link TeamOrPersonBase#getNomenclaturalTitle() abbreviated names}
179 * of all persons belonging to its (ordered) members' list if the flag
180 * {@link #protectedNomenclaturalTitleCache protectedNomenclaturalTitleCache} is not set.
181 * Otherwise this method returns the present nomenclatural abbreviation.
182 * In case the string is generated the cache strategy used is defined in
183 * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}.
184 * The result might be kept as nomenclatural abbreviation
185 * by using the {@link #setNomenclaturalTitle(String) setNomenclaturalTitle} method.
186 *
187 * @return a string which identifies <i>this</i> team for nomenclature
188 */
189 @Override
190 @Transient
191 public String getNomenclaturalTitle() {
192 if (protectedNomenclaturalTitleCache == PROTECTED){
193 return this.nomenclaturalTitle;
194 }
195 if (nomenclaturalTitle == null){
196 this.nomenclaturalTitle = cacheStrategy.getNomenclaturalTitle(this);
197 }else{
198 //as long as team members to not inform the team about changes the cache must be created new each time
199 nomenclaturalTitle = cacheStrategy.getNomenclaturalTitle(this);
200 }
201 return nomenclaturalTitle;
202 }
203
204 /**
205 * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
206 * and protects it from overwriting.
207 * This method overrides {@link TeamOrPersonBase#setNomenclaturalTitle(String) setNomenclaturalTitle}.
208 *
209 * @see #getNomenclaturalTitle()
210 * @see #setNomenclaturalTitle(String, boolean)
211 */
212 @Override
213 public void setNomenclaturalTitle(String nomenclaturalTitle) {
214 setNomenclaturalTitle(nomenclaturalTitle, PROTECTED);
215 this.nomenclaturalTitle = nomenclaturalTitle;
216 }
217
218 /**
219 * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
220 * and a protection flag status to this string.
221 *
222 * @see #getNomenclaturalTitle()
223 */
224 public void setNomenclaturalTitle(String nomenclaturalTitle, boolean protectedNomenclaturalTitleCache) {
225 this.nomenclaturalTitle = nomenclaturalTitle;
226 this.protectedNomenclaturalTitleCache = protectedNomenclaturalTitleCache;
227 }
228
229 /* (non-Javadoc)
230 * @see eu.etaxonomy.cdm.model.agent.TeamOrPersonBase#getTitleCache()
231 */
232 @Override
233 public String getTitleCache() {
234 isGeneratingTitleCache = true;
235 String result = "";
236 if (isProtectedTitleCache()){
237 result = this.titleCache;
238 }else{
239 result = generateTitle();
240 result = replaceEmptyTitleByNomTitle(result);
241 result = getTruncatedCache(result);
242 }
243 isGeneratingTitleCache = false;
244 return result;
245 }
246 }