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 / Person.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 eu.etaxonomy.cdm.model.common.TimePeriod;
13 import eu.etaxonomy.cdm.model.common.Keyword;
14 import eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy;
15
16 import org.apache.log4j.Logger;
17 import org.hibernate.annotations.Cascade;
18 import org.hibernate.annotations.CascadeType;
19 import org.hibernate.envers.Audited;
20 import org.hibernate.search.annotations.Field;
21 import org.hibernate.search.annotations.Index;
22 import org.hibernate.search.annotations.Indexed;
23 import org.hibernate.search.annotations.IndexedEmbedded;
24 import org.springframework.beans.factory.annotation.Configurable;
25
26 import java.util.*;
27 import javax.persistence.*;
28 import javax.xml.bind.annotation.XmlAccessType;
29 import javax.xml.bind.annotation.XmlAccessorType;
30 import javax.xml.bind.annotation.XmlElement;
31 import javax.xml.bind.annotation.XmlElementWrapper;
32 import javax.xml.bind.annotation.XmlIDREF;
33 import javax.xml.bind.annotation.XmlRootElement;
34 import javax.xml.bind.annotation.XmlSchemaType;
35 import javax.xml.bind.annotation.XmlType;
36
37 /**
38 * This class represents human beings, living or dead.<BR>
39 * It includes name parts, {@link Contact contact} details, {@link InstitutionalMembership institutional membership},
40 * and other possible information such as life {@link TimePeriod time period},
41 * taxonomic and/or geographical {@link Keyword specialization}.
42 * For a short abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
43 * is to be used.<BR>
44 * For other alternative (string-)names {@link eu.etaxonomy.cdm.model.common.OriginalSource OriginalSource} instances must be created
45 * and the inherited attribute {@link eu.etaxonomy.cdm.model.common.ReferencedEntityBase#getOriginalNameString() originalNameString} must be used.
46 * <P>
47 * This class corresponds to: <ul>
48 * <li> Person according to the TDWG ontology
49 * <li> AgentName (partially) according to the TCS
50 * <li> Person (PersonName partially) according to the ABCD schema
51 * </ul>
52 *
53 * @author m.doering
54 * @version 1.0
55 * @created 08-Nov-2007 13:06:42
56 */
57 @XmlAccessorType(XmlAccessType.FIELD)
58 @XmlType(name = "Person", propOrder = {
59 "prefix",
60 "firstname",
61 "lastname",
62 "suffix",
63 "lifespan",
64 "institutionalMemberships",
65 "keywords"
66 })
67 @XmlRootElement(name = "Person")
68 @Entity
69 @Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
70 @Audited
71 @Configurable
72 public class Person extends TeamOrPersonBase<Person> {
73 private static final long serialVersionUID = 4153566493065539763L;
74 public static final Logger logger = Logger.getLogger(Person.class);
75
76 @XmlElement(name = "Prefix")
77 @Field(index=Index.TOKENIZED)
78 private String prefix;
79
80 @XmlElement(name = "FirstName")
81 @Field(index=Index.TOKENIZED)
82 private String firstname;
83
84 @XmlElement(name = "LastName")
85 @Field(index=Index.TOKENIZED)
86 private String lastname;
87
88 @XmlElement(name = "Suffix")
89 @Field(index=Index.TOKENIZED)
90 private String suffix;
91
92 @XmlElement(name = "Lifespan")
93 @IndexedEmbedded
94 private TimePeriod lifespan;
95
96 @XmlElementWrapper(name = "InstitutionalMemberships")
97 @XmlElement(name = "InstitutionalMembership")
98 @OneToMany(fetch=FetchType.LAZY, mappedBy = "person")
99 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
100 protected Set<InstitutionalMembership> institutionalMemberships;
101
102 @XmlElementWrapper(name = "Keywords")
103 @XmlElement(name = "Keyword")
104 @XmlIDREF
105 @XmlSchemaType(name="IDREF")
106 @ManyToMany(fetch=FetchType.LAZY)
107 @JoinTable(
108 name="Person_Keyword",
109 joinColumns=@JoinColumn(name="person_fk"),
110 inverseJoinColumns=@JoinColumn(name="keyword_fk")
111 )
112 private Set<Keyword> keywords = new HashSet<Keyword>();
113
114 /**
115 * Creates a new empty instance for a person whose existence is all what is known.
116 * This can be a provisional solution until more information about <i>this</i> person
117 * can be gathered, for instance in case a member of a nomenclatural author team
118 * is not explicitly mentioned. It also includes the cache strategy defined in
119 * {@link eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy PersonDefaultCacheStrategy}.
120 */
121 public static Person NewInstance(){
122 return new Person();
123 }
124
125 /**
126 * Creates a new instance for a person for whom an "identification" string
127 * is all what is known. This string is generally a short or a complete name.
128 * As this string is kept in the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache}
129 * attribute and should not be overwritten by the {@link #generateTitle() generateTitle} method
130 * the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#isProtectedTitleCache() protectedTitleCache} flag will be turned on.
131 */
132 public static Person NewTitledInstance(String titleCache){
133 Person result = new Person();
134 result.setTitleCache(titleCache);
135 return result;
136 }
137
138
139 /**
140 * Class constructor.
141 *
142 * @see #Person(String, String, String)
143 */
144 protected Person() {
145 super();
146 this.cacheStrategy = PersonDefaultCacheStrategy.NewInstance();
147
148 }
149
150 /**
151 * Class constructor using a "forenames" string (including initials),
152 * a surname (family name) and an abbreviated name as used in nomenclature.
153 * For the abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
154 * is used.
155 *
156 * @param firstname the given name
157 * @param lastname the hereditary name
158 * @param nomenclaturalTitel the abbreviated name
159 * @see #Person()
160 * @see #NewInstance()
161 */
162 public Person(String firstname, String lastname, String nomenclaturalTitel) {
163 this.setFirstname(firstname);
164 this.setLastname(lastname);
165 this.setNomenclaturalTitle(nomenclaturalTitel);
166 }
167
168
169 /**
170 * Returns the set of {@link InstitutionalMembership institution memberships} corresponding to <i>this</i> person.
171 *
172 * @see InstitutionalMembership
173 */
174 public Set<InstitutionalMembership> getInstitutionalMemberships(){
175 return this.institutionalMemberships;
176 }
177
178
179 /**
180 * Adds a new {@link InstitutionalMembership membership} of <i>this</i> person in an {@link Institution institution}
181 * to the set of his institution memberships.
182 * This method also creates a new institutional membership instance.
183 *
184 * @param institution the institution <i>this</i> person belongs to
185 * @param period the time period for which <i>this</i> person has been a member of the institution
186 * @param department the string label for the department <i>this</i> person belongs to,
187 * within the institution
188 * @param role the string label for the persons's role within the department or institution
189 * @see #getInstitutionalMemberships()
190 * @see InstitutionalMembership#InstitutionalMembership(Institution, Person, TimePeriod, String, String)
191 */
192 public void addInstitutionalMembership(Institution institution, TimePeriod period, String department, String role){
193 //TODO to be implemented?
194 logger.warn("not yet fully implemented?");
195 InstitutionalMembership ims = new InstitutionalMembership(institution, this, period, department, role);
196 institutionalMemberships.add(ims);
197 }
198
199 /**
200 * Removes one element from the set of institutional memberships of <i>this</i> person.
201 * Institute and person attributes of the institutional membership object
202 * will be nullified.
203 *
204 * @param ims the institutional membership of <i>this</i> person which should be deleted
205 * @see #getInstitutionalMemberships()
206 */
207 public void removeInstitutionalMembership(InstitutionalMembership ims){
208 //TODO to be implemented?
209 logger.warn("not yet fully implemented?");
210 ims.setInstitute(null);
211 ims.setPerson(null);
212 this.institutionalMemberships.remove(ims);
213 }
214
215
216 /**
217 * Returns the set of {@link eu.etaxonomy.cdm.model.common.Keyword keywords} mostly representing a taxonomic or
218 * a geographical specialization of <i>this</i> person.
219 * Keywords are items of a controlled {@link eu.etaxonomy.cdm.model.common.TermVocabulary vocabulary}.
220 *
221 * @see Keyword
222 */
223 public Set<Keyword> getKeywords(){
224 return this.keywords;
225 }
226
227 /**
228 * Adds a new keyword from the keyword vocabulary to the set of keywords
229 * describing or circumscribing <i>this</i> person's activities.
230 *
231 * @param keyword any keyword
232 * @see #getKeywords()
233 * @see eu.etaxonomy.cdm.model.common.Keyword
234 */
235 public void addKeyword(Keyword keyword){
236 this.keywords.add(keyword);
237 }
238 /**
239 * Removes one element from the set of keywords for <i>this</i> person.
240 *
241 * @param keyword the keyword which should be deleted
242 * @see #getKeywords()
243 */
244 public void removeKeyword(Keyword keyword){
245 this.keywords.remove(keyword);
246 }
247
248 /**
249 * Returns the string representing the prefix (for instance "Prof.&nbsp;Dr.<!-- -->")
250 * to <i>this</i> person's name.
251 */
252 public String getPrefix(){
253 return this.prefix;
254 }
255 /**
256 * @see #getPrefix()
257 */
258 public void setPrefix(String prefix){
259 this.prefix = prefix;
260 }
261
262
263 /**
264 * Returns the string representing the given name or forename
265 * (for instance "John") of <i>this</i> person.
266 * This is the part of his name which is not shared with other
267 * family members. Actually it may be just initials (for instance "G.&nbsp;Jr."),
268 * all forenames in full or a combination of expanded names and initials.
269 */
270 public String getFirstname(){
271 return this.firstname;
272 }
273 /**
274 * @see #getFirstname()
275 */
276 public void setFirstname(String firstname){
277 this.firstname = firstname;
278 }
279
280
281 /**
282 * Returns the string representing the hereditary name (surname or family name)
283 * (for instance "Smith") of <i>this</i> person.
284 * This is the part of his name which is common to (all) other
285 * members of his family, as distinct from the given name or forename.
286 */
287 public String getLastname(){
288 return this.lastname;
289 }
290 /**
291 * @see #getLastname()
292 */
293 public void setLastname(String lastname){
294 this.lastname = lastname;
295 }
296
297
298 /**
299 * Returns the string representing the suffix (for instance "Junior")
300 * of <i>this</i> person's name.
301 */
302 public String getSuffix(){
303 return this.suffix;
304 }
305 /**
306 * @see #getSuffix()
307 */
308 public void setSuffix(String suffix){
309 this.suffix = suffix;
310 }
311
312
313 /**
314 * Returns the {@link eu.etaxonomy.cdm.model.common.TimePeriod period of time}
315 * in which <i>this</i> person was alive (life span).
316 * The general form is birth date - death date
317 * (XXXX - YYYY; XXXX - or - YYYY as appropriate),
318 * but a simple flourished date (fl. XXXX) is also possible
319 * if that is all what is known.
320 *
321 * @see eu.etaxonomy.cdm.model.common.TimePeriod
322 */
323 public TimePeriod getLifespan(){
324 return this.lifespan;
325 }
326 /**
327 * @see #getLifespan()
328 */
329 public void setLifespan(TimePeriod lifespan){
330 this.lifespan = lifespan;
331 }
332
333 // /**
334 // * Generates the "full" name string of <i>this</i> person according to the strategy
335 // * defined in {@link eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy PersonDefaultCacheStrategy}.
336 // * The used attributes are:
337 // * {@link #getPrefix() prefix}, {@link #getFirstname() firstname}, {@link #getLastname() lastname} and {@link #getSuffix() suffix}.
338 // * This method overrides {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() generateTitle}.
339 // * The result might be kept as {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(String) titleCache} if the
340 // * flag {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#protectedTitleCache protectedTitleCache} is not set.
341 // *
342 // * @return the string with the full name of <i>this</i> person
343 // */
344 // @Override
345 // public String generateTitle() {
346 // String title = null;
347 // if (cacheStrategy != null) {
348 // title = cacheStrategy.getTitleCache(this);
349 // }
350 // return title;
351 // }
352
353 }