Project

General

Profile

Download (13.5 KB) Statistics
| Branch: | Tag: | Revision:
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.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;
25

    
26
import org.apache.commons.lang.StringUtils;
27
import org.apache.log4j.Logger;
28
import org.hibernate.annotations.Cascade;
29
import org.hibernate.annotations.CascadeType;
30
import org.hibernate.envers.Audited;
31
import org.hibernate.search.annotations.Field;
32
import org.hibernate.search.annotations.IndexedEmbedded;
33
import org.joda.time.Partial;
34
import org.springframework.beans.factory.annotation.Configurable;
35

    
36
import eu.etaxonomy.cdm.model.common.TimePeriod;
37
import eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy;
38
import eu.etaxonomy.cdm.strategy.match.Match;
39
import eu.etaxonomy.cdm.strategy.match.MatchMode;
40
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
41
import javassist.compiler.ast.Keyword;
42

    
43
/**
44
 * This class represents human beings, living or dead.<BR>
45
 * It includes name parts, {@link Contact contact} details, {@link InstitutionalMembership institutional membership},
46
 * and other possible information such as life {@link TimePeriod time period},
47
 * taxonomic and/or geographical {@link Keyword specialization}.
48
 * For a short abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
49
 * is to be used.<BR>
50
 * For other alternative (string-)names {@link eu.etaxonomy.cdm.model.common.OriginalSourceBase OriginalSource} instances must be created
51
 * and the inherited attribute {@link eu.etaxonomy.cdm.model.common.ReferencedEntityBase#getOriginalNameString() originalNameString} must be used.
52
 * <P>
53
 * This class corresponds to: <ul>
54
 * <li> Person according to the TDWG ontology
55
 * <li> AgentName (partially) according to the TCS
56
 * <li> Person (PersonName partially) according to the ABCD schema
57
 * </ul>
58
 *
59
 * @author m.doering
60
 * @created 08-Nov-2007 13:06:42
61
 */
62
@XmlAccessorType(XmlAccessType.FIELD)
63
@XmlType(name = "Person", propOrder = {
64
	    "prefix",
65
	    "firstname",
66
	    "initials",
67
	    "lastname",
68
	    "suffix",
69
	    "lifespan",
70
	    "institutionalMemberships"
71
})
72
@XmlRootElement(name = "Person")
73
@Entity
74
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
75
//@Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
76
@Audited
77
@Configurable
78
public class Person extends TeamOrPersonBase<Person>{
79
	private static final long serialVersionUID = 4153566493065539763L;
80
	public static final Logger logger = Logger.getLogger(Person.class);
81

    
82
    @XmlElement(name = "Prefix")
83
    @Field
84
  //TODO Val #3379
85
//    @NullOrNotEmpty
86
    @Column(length=255)
87
	private String prefix;
88

    
89
    @XmlElement(name = "FirstName")
90
    @Field
91
  //TODO Val #3379
92
//    @NullOrNotEmpty
93
    @Column(length=255)
94
	private String firstname;
95

    
96
    @XmlElement(name = "FirstName")
97
    @Field
98
    @NullOrNotEmpty
99
    @Column(length=50)
100
    private String initials;
101

    
102
    @XmlElement(name = "LastName")
103
    @Field
104
  //TODO Val #3379
105
//    @NullOrNotEmpty
106
    @Column(length=255)
107
	private String lastname;
108

    
109
    @XmlElement(name = "Suffix")
110
    @Field
111
  //TODO Val #3379
112
//    @NullOrNotEmpty
113
    @Column(length=255)
114
	private String suffix;
115

    
116
    @XmlElement(name = "Lifespan")
117
    @IndexedEmbedded
118
    @Match(value=MatchMode.EQUAL_OR_ONE_NULL)
119
  //TODO Val #3379    check carefully what the condition is that lifespan is really null in legacy data
120
//    @NotNull
121
	private TimePeriod lifespan = TimePeriod.NewInstance();
122

    
123
    @XmlElementWrapper(name = "InstitutionalMemberships", nillable = true)
124
    @XmlElement(name = "InstitutionalMembership")
125
    @OneToMany(fetch=FetchType.LAZY, mappedBy = "person")
126
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
127
	protected Set<InstitutionalMembership> institutionalMemberships;
128

    
129
// *********************** FACTORY **********************************/
130

    
131
	/**
132
	 * Creates a new empty instance for a person whose existence is all what is known.
133
	 * This can be a provisional solution until more information about <i>this</i> person
134
	 * can be gathered, for instance in case a member of a nomenclatural author team
135
	 * is not explicitly mentioned. It also includes the cache strategy defined in
136
	 * {@link eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy PersonDefaultCacheStrategy}.
137
	 */
138
	public static Person NewInstance(){
139
		return new Person();
140
	}
141

    
142
	/**
143
	 * Creates a new instance for a person for whom an "identification" string
144
	 * is all what is known. This string is generally a short or a complete name.
145
	 * As this string is kept in the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache}
146
	 * attribute and should not be overwritten by the {@link #generateTitle() generateTitle} method
147
	 * the {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#isProtectedTitleCache() protectedTitleCache} flag will be turned on.
148
	 */
149
	public static Person NewTitledInstance(String titleCache){
150
		Person result = new Person();
151
		result.setTitleCache(titleCache, true);
152
		return result;
153
	}
154

    
155
// *********************** CONSTRUCTOR **********************************/
156

    
157
	/**
158
	 * Class constructor.
159
	 *
160
	 * @see #Person(String, String, String)
161
	 */
162
	protected Person() {
163
		super();
164
		this.cacheStrategy = PersonDefaultCacheStrategy.NewInstance();
165

    
166
	}
167

    
168
	/**
169
	 * Class constructor using a "forenames" string (including initials),
170
	 * a surname (family name) and an abbreviated name as used in nomenclature.
171
	 * For the abbreviated name the inherited attribute {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle}
172
	 * is used.
173
	 *
174
	 * @param  firstname     		the given name
175
	 * @param  lastname      		the hereditary name
176
	 * @param  nomenclaturalTitel 	the abbreviated name
177
	 * @see                  		#Person()
178
	 * @see                  		#NewInstance()
179
	 */
180
	public Person(String firstname, String lastname, String nomenclaturalTitel) {
181
		this.setFirstname(firstname);
182
		this.setLastname(lastname);
183
		logger.debug("before - Set nomenclatural Title");
184
		this.setNomenclaturalTitle(nomenclaturalTitel);
185
		logger.debug("after - Set nomenclatural Title");
186
	}
187

    
188
// *********************** GETTER SETTER ADDER **********************************/
189

    
190
	/**
191
	 * Returns the set of {@link InstitutionalMembership institution memberships} corresponding to <i>this</i> person.
192
	 *
193
	 * @see     InstitutionalMembership
194
	 */
195
	public Set<InstitutionalMembership> getInstitutionalMemberships(){
196
		if(institutionalMemberships == null) {
197
			this.institutionalMemberships = new HashSet<InstitutionalMembership>();
198
		}
199
		return this.institutionalMemberships;
200
	}
201

    
202
	protected void addInstitutionalMembership(InstitutionalMembership ims){
203
		getInstitutionalMemberships().add(ims);
204
		if (ims.getPerson() != this){
205
			logger.warn("Institutional membership's person has to be changed for adding it to person: " + this);
206
			ims.getPerson().removeInstitutionalMembership(ims);
207
			ims.setPerson(this);
208

    
209
		}
210
	}
211

    
212
	/**
213
	 * Adds a new {@link InstitutionalMembership membership} of <i>this</i> person in an {@link Institution institution}
214
	 * to the set of his institution memberships.
215
	 * This method also creates a new institutional membership instance.
216
	 *
217
	 * @param  institution  the institution <i>this</i> person belongs to
218
	 * @param  period       the time period for which <i>this</i> person has been a member of the institution
219
	 * @param  department   the string label for the department <i>this</i> person belongs to,
220
	 * 					    within the institution
221
	 * @param  role         the string label for the persons's role within the department or institution
222
	 * @see 			    #getInstitutionalMemberships()
223
	 * @see 			    InstitutionalMembership#InstitutionalMembership(Institution, Person, TimePeriod, String, String)
224
	 */
225
	public InstitutionalMembership addInstitutionalMembership(Institution institution, TimePeriod period, String department, String role){
226
		return new InstitutionalMembership(institution, this, period, department, role);
227
	}
228

    
229
	/**
230
	 * Removes one element from the set of institutional memberships of <i>this</i> person.
231
	 * Institute and person attributes of the institutional membership object
232
	 * will be nullified.
233
	 *
234
	 * @param  ims  the institutional membership of <i>this</i> person which should be deleted
235
	 * @see     	#getInstitutionalMemberships()
236
	 */
237
	public void removeInstitutionalMembership(InstitutionalMembership ims){
238
		ims.setInstitute(null);
239
		ims.setPerson(null);
240
		getInstitutionalMemberships().remove(ims);
241
	}
242

    
243
	/**
244
	 * Returns the string representing the prefix (for instance "Prof.&nbsp;Dr.<!-- -->")
245
	 * to <i>this</i> person's name.
246
	 */
247
	public String getPrefix(){
248
		return this.prefix;
249
	}
250
	/**
251
	 * @see  #getPrefix()
252
	 */
253
	public void setPrefix(String prefix){
254
		this.prefix = StringUtils.isBlank(prefix) ? null : prefix;
255
	}
256

    
257

    
258
	/**
259
	 * Returns the string representing the given name or forename
260
	 * (for instance "John") of <i>this</i> person.
261
	 * This is the part of his name which is not shared with other
262
	 * family members. Actually it may be just initials (for instance "G.&nbsp;Jr."),
263
	 * all forenames in full or a combination of expanded names and initials.
264
	 */
265
	public String getFirstname(){
266
		return this.firstname;
267
	}
268
	/**
269
	 * @see  #getFirstname()
270
	 */
271
	public void setFirstname(String firstname){
272
		this.firstname = StringUtils.isBlank(firstname) ? null : firstname;
273
	}
274

    
275
    /**
276
     * Returns the initials of this person as used in bibliographic
277
     * references. Usually these are the first letters of each firstname
278
     * followed by "." per firstname. For East Asian names it may
279
     * be the first 2 letters. Also dashes are kept.
280
     * @return the initials
281
     */
282
    public String getInitials(){
283
        return this.initials;
284
    }
285
    /**
286
     * @see  #getInitals()
287
     */
288
    public void setInitials(String initials){
289
        this.initials = isBlank(initials) ? null : initials;
290
    }
291

    
292

    
293
	/**
294
	 * Returns the string representing the hereditary name (surname or family name)
295
	 * (for instance "Smith") of <i>this</i> person.
296
	 * This is the part of his name which is common to (all) other
297
	 * members of his family, as distinct from the given name or forename.
298
	 */
299
	public String getLastname(){
300
		return this.lastname;
301
	}
302
	/**
303
	 * @see  #getLastname()
304
	 */
305
	public void setLastname(String lastname){
306
		this.lastname = StringUtils.isBlank(lastname) ? null : lastname;
307
	}
308

    
309

    
310
	/**
311
	 * Returns the string representing the suffix (for instance "Junior")
312
	 * of <i>this</i> person's name.
313
	 */
314
	public String getSuffix(){
315
		return this.suffix;
316
	}
317
	/**
318
	 * @see  #getSuffix()
319
	 */
320
	public void setSuffix(String suffix){
321
		this.suffix = StringUtils.isBlank(suffix) ? null: suffix;
322
	}
323

    
324

    
325
	/**
326
	 * Returns the {@link eu.etaxonomy.cdm.model.common.TimePeriod period of time}
327
	 * in which <i>this</i> person was alive (life span).
328
	 * The general form is birth date - death date
329
	 * (XXXX - YYYY; XXXX - or - YYYY as appropriate),
330
	 * but a simple flourished date (fl. XXXX) is also possible
331
	 * if that is all what is known.
332
	 *
333
	 * @see  eu.etaxonomy.cdm.model.common.TimePeriod
334
	 */
335
	public TimePeriod getLifespan(){
336
		if(lifespan == null) {
337
			this.lifespan = TimePeriod.NewInstance(new Partial(), new Partial());
338
		}
339
		return this.lifespan;
340
	}
341
	/**
342
	 * @see  #getLifespan()
343
	 */
344
	public void setLifespan(TimePeriod lifespan){
345
		if (lifespan == null){
346
			this.lifespan = TimePeriod.NewInstance(new Partial(), new Partial());
347
		}
348
		this.lifespan = lifespan;
349
	}
350

    
351
//	/**
352
//	 * Generates the "full" name string of <i>this</i> person according to the strategy
353
//	 * defined in {@link eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy PersonDefaultCacheStrategy}.
354
//	 * The used attributes are:
355
//	 * {@link #getPrefix() prefix}, {@link #getFirstname() firstname}, {@link #getLastname() lastname} and {@link #getSuffix() suffix}.
356
//	 * This method overrides {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() generateTitle}.
357
//	 * The result might be kept as {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#setTitleCache(String) titleCache} if the
358
//	 * flag {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#protectedTitleCache protectedTitleCache} is not set.
359
//	 *
360
//	 * @return  the string with the full name of <i>this</i> person
361
//	 */
362
//	@Override
363
//	public String generateTitle() {
364
//		String title = null;
365
//		if (cacheStrategy != null) {
366
//		title = cacheStrategy.getTitleCache(this);
367
//		}
368
//        return title;
369
//	}
370

    
371
//*********************** CLONE ********************************************************/
372

    
373
	/**
374
	 * Clones <i>this</i> Person. This is a shortcut that enables to create
375
	 * a new instance that differs only slightly from <i>this</i> Person.
376
	 *
377
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
378
	 * @see java.lang.Object#clone()
379
	 */
380
	@Override
381
	public Object clone() {
382
		try{
383
			Person result = (Person)super.clone();
384
			//no changes to firstname, lastname, lifespan, prefix, suffix
385
			return result;
386
		} catch (CloneNotSupportedException e){
387
			logger.warn("Object does not implement cloneable");
388
			e.printStackTrace();
389
			return null;
390
		}
391

    
392

    
393
	}
394

    
395
}
(7-7/11)