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