2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.agent
;
12 import java
.util
.HashSet
;
15 import javax
.persistence
.Column
;
16 import javax
.persistence
.Entity
;
17 import javax
.persistence
.FetchType
;
18 import javax
.persistence
.OneToMany
;
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
.XmlRootElement
;
24 import javax
.xml
.bind
.annotation
.XmlType
;
26 import org
.apache
.log4j
.Logger
;
27 import org
.hibernate
.annotations
.Cascade
;
28 import org
.hibernate
.annotations
.CascadeType
;
29 import org
.hibernate
.envers
.Audited
;
30 import org
.hibernate
.search
.annotations
.Field
;
31 import org
.hibernate
.search
.annotations
.IndexedEmbedded
;
32 import org
.joda
.time
.Partial
;
33 import org
.springframework
.beans
.factory
.annotation
.Configurable
;
35 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
36 import eu
.etaxonomy
.cdm
.strategy
.cache
.agent
.PersonDefaultCacheStrategy
;
37 import eu
.etaxonomy
.cdm
.strategy
.match
.Match
;
38 import eu
.etaxonomy
.cdm
.strategy
.match
.MatchMode
;
39 import eu
.etaxonomy
.cdm
.validation
.annotation
.NullOrNotEmpty
;
40 import javassist
.compiler
.ast
.Keyword
;
43 * This class represents human beings, living or dead.<BR>
44 * It includes name parts, {@link Contact contact} details, {@link InstitutionalMembership institutional membership},
45 * and other possible information such as life {@link TimePeriod time period},
46 * taxonomic and/or geographical {@link Keyword specialization}.
47 * For a short abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
49 * For other alternative (string-)names {@link eu.etaxonomy.cdm.model.common.OriginalSourceBase OriginalSource} instances must be created
50 * and the inherited attribute {@link eu.etaxonomy.cdm.model.common.ReferencedEntityBase#getOriginalNameString() originalNameString} must be used.
52 * This class corresponds to: <ul>
53 * <li> Person according to the TDWG ontology
54 * <li> AgentName (partially) according to the TCS
55 * <li> Person (PersonName partially) according to the ABCD schema
59 * @created 08-Nov-2007 13:06:42
61 @XmlAccessorType(XmlAccessType
.FIELD
)
62 @XmlType(name
= "Person", propOrder
= {
69 "institutionalMemberships"
71 @XmlRootElement(name
= "Person")
73 //@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
74 //@Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
77 public class Person
extends TeamOrPersonBase
<Person
>{
78 private static final long serialVersionUID
= 4153566493065539763L;
79 public static final Logger logger
= Logger
.getLogger(Person
.class);
81 @XmlElement(name
= "Prefix")
86 private String prefix
;
88 @XmlElement(name
= "FirstName")
93 private String firstname
;
95 @XmlElement(name
= "FirstName")
99 private String initials
;
101 @XmlElement(name
= "LastName")
106 private String lastname
;
108 @XmlElement(name
= "Suffix")
113 private String suffix
;
115 @XmlElement(name
= "Lifespan")
117 @Match(value
=MatchMode
.EQUAL_OR_ONE_NULL
)
118 //TODO Val #3379 check carefully what the condition is that lifespan is really null in legacy data
120 private TimePeriod lifespan
= TimePeriod
.NewInstance();
122 @XmlElementWrapper(name
= "InstitutionalMemberships", nillable
= true)
123 @XmlElement(name
= "InstitutionalMembership")
124 @OneToMany(fetch
=FetchType
.LAZY
, mappedBy
= "person")
125 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
126 protected Set
<InstitutionalMembership
> institutionalMemberships
;
128 // *********************** FACTORY **********************************/
131 * Creates a new empty instance for a person whose existence is all what is known.
132 * This can be a provisional solution until more information about <i>this</i> person
133 * can be gathered, for instance in case a member of a nomenclatural author team
134 * is not explicitly mentioned. It also includes the cache strategy defined in
135 * {@link eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy PersonDefaultCacheStrategy}.
137 public static Person
NewInstance(){
142 * Creates a new instance for a person for whom an "identification" string
143 * is all what is known. This string is generally a short or a complete name.
144 * As this string is kept in the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache}
145 * attribute and should not be overwritten by the {@link #generateTitle() generateTitle} method
146 * the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#isProtectedTitleCache() protectedTitleCache} flag will be turned on.
148 public static Person
NewTitledInstance(String titleCache
){
149 Person result
= new Person();
150 result
.setTitleCache(titleCache
, true);
154 // *********************** CONSTRUCTOR **********************************/
159 * @see #Person(String, String, String)
163 this.cacheStrategy
= PersonDefaultCacheStrategy
.NewInstance();
168 * Class constructor using a "forenames" string (including initials),
169 * a surname (family name) and an abbreviated name as used in nomenclature.
170 * For the abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
173 * @param firstname the given name
174 * @param lastname the hereditary name
175 * @param nomenclaturalTitel the abbreviated name
177 * @see #NewInstance()
179 public Person(String firstname
, String lastname
, String nomenclaturalTitel
) {
180 this.setFirstname(firstname
);
181 this.setLastname(lastname
);
182 logger
.debug("before - Set nomenclatural Title");
183 this.setNomenclaturalTitle(nomenclaturalTitel
);
184 logger
.debug("after - Set nomenclatural Title");
187 // *********************** GETTER SETTER ADDER **********************************/
190 * Returns the set of {@link InstitutionalMembership institution memberships} corresponding to <i>this</i> person.
192 * @see InstitutionalMembership
194 public Set
<InstitutionalMembership
> getInstitutionalMemberships(){
195 if(institutionalMemberships
== null) {
196 this.institutionalMemberships
= new HashSet
<InstitutionalMembership
>();
198 return this.institutionalMemberships
;
201 protected void addInstitutionalMembership(InstitutionalMembership ims
){
202 getInstitutionalMemberships().add(ims
);
203 if (ims
.getPerson() != this){
204 logger
.warn("Institutional membership's person has to be changed for adding it to person: " + this);
205 ims
.getPerson().removeInstitutionalMembership(ims
);
212 * Adds a new {@link InstitutionalMembership membership} of <i>this</i> person in an {@link Institution institution}
213 * to the set of his institution memberships.
214 * This method also creates a new institutional membership instance.
216 * @param institution the institution <i>this</i> person belongs to
217 * @param period the time period for which <i>this</i> person has been a member of the institution
218 * @param department the string label for the department <i>this</i> person belongs to,
219 * within the institution
220 * @param role the string label for the persons's role within the department or institution
221 * @see #getInstitutionalMemberships()
222 * @see InstitutionalMembership#InstitutionalMembership(Institution, Person, TimePeriod, String, String)
224 public InstitutionalMembership
addInstitutionalMembership(Institution institution
, TimePeriod period
, String department
, String role
){
225 return new InstitutionalMembership(institution
, this, period
, department
, role
);
229 * Removes one element from the set of institutional memberships of <i>this</i> person.
230 * Institute and person attributes of the institutional membership object
233 * @param ims the institutional membership of <i>this</i> person which should be deleted
234 * @see #getInstitutionalMemberships()
236 public void removeInstitutionalMembership(InstitutionalMembership ims
){
237 ims
.setInstitute(null);
239 getInstitutionalMemberships().remove(ims
);
243 * Returns the string representing the prefix (for instance "Prof. Dr.<!-- -->")
244 * to <i>this</i> person's name.
246 public String
getPrefix(){
252 public void setPrefix(String prefix
){
253 this.prefix
= isBlank(prefix
) ?
null : prefix
;
258 * Returns the string representing the given name or forename
259 * (for instance "John") of <i>this</i> person.
260 * This is the part of his name which is not shared with other
261 * family members. Actually it may be just initials (for instance "G. Jr."),
262 * all forenames in full or a combination of expanded names and initials.
264 public String
getFirstname(){
265 return this.firstname
;
268 * @see #getFirstname()
270 public void setFirstname(String firstname
){
271 this.firstname
= isBlank(firstname
) ?
null : firstname
;
275 * Returns the initials of this person as used in bibliographic
276 * references. Usually these are the first letters of each firstname
277 * followed by "." per firstname. For East Asian names it may
278 * be the first 2 letters. Also dashes are kept.
279 * @return the initials
281 public String
getInitials(){
282 return this.initials
;
287 public void setInitials(String initials
){
288 this.initials
= isBlank(initials
) ?
null : initials
;
293 * Returns the string representing the hereditary name (surname or family name)
294 * (for instance "Smith") of <i>this</i> person.
295 * This is the part of his name which is common to (all) other
296 * members of his family, as distinct from the given name or forename.
298 public String
getLastname(){
299 return this.lastname
;
302 * @see #getLastname()
304 public void setLastname(String lastname
){
305 this.lastname
= isBlank(lastname
) ?
null : lastname
;
310 * Returns the string representing the suffix (for instance "Junior")
311 * of <i>this</i> person's name.
313 public String
getSuffix(){
319 public void setSuffix(String suffix
){
320 this.suffix
= isBlank(suffix
) ?
null: suffix
;
325 * Returns the {@link eu.etaxonomy.cdm.model.common.TimePeriod period of time}
326 * in which <i>this</i> person was alive (life span).
327 * The general form is birth date - death date
328 * (XXXX - YYYY; XXXX - or - YYYY as appropriate),
329 * but a simple flourished date (fl. XXXX) is also possible
330 * if that is all what is known.
332 * @see eu.etaxonomy.cdm.model.common.TimePeriod
334 public TimePeriod
getLifespan(){
335 if(lifespan
== null) {
336 this.lifespan
= TimePeriod
.NewInstance(new Partial(), new Partial());
338 return this.lifespan
;
341 * @see #getLifespan()
343 public void setLifespan(TimePeriod lifespan
){
344 if (lifespan
== null){
345 this.lifespan
= TimePeriod
.NewInstance(new Partial(), new Partial());
347 this.lifespan
= lifespan
;
350 //*********************** CLONE ********************************************************/
353 * Clones <i>this</i> Person. This is a shortcut that enables to create
354 * a new instance that differs only slightly from <i>this</i> Person.
356 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
357 * @see java.lang.Object#clone()
360 public Object
clone() {
362 Person result
= (Person
)super.clone();
363 //no changes to firstname, lastname, lifespan, prefix, suffix
365 } catch (CloneNotSupportedException e
){
366 logger
.warn("Object does not implement cloneable");