Project

General

Profile

Download (11.1 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.beans.PropertyChangeEvent;
13
import java.beans.PropertyChangeListener;
14
import java.util.ArrayList;
15
import java.util.List;
16

    
17
import javax.persistence.Entity;
18
import javax.persistence.FetchType;
19
import javax.persistence.ManyToMany;
20
import javax.persistence.Transient;
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.annotations.IndexColumn;
34
import org.hibernate.envers.Audited;
35
import org.hibernate.search.annotations.Indexed;
36
import org.springframework.beans.factory.annotation.Configurable;
37

    
38
import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy;
39
import eu.etaxonomy.cdm.strategy.match.Match;
40
import eu.etaxonomy.cdm.strategy.match.MatchMode;
41

    
42
/**
43
 * This class represents teams of {@link Person persons}. A team exists either for itself
44
 * or is built with the list of (distinct) persons who belong to it.
45
 * In the first case the inherited attribute {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} is to be used.
46
 * In the second case at least all abbreviated names
47
 * (the inherited attributes {@link TeamOrPersonBase#getNomenclaturalTitle() nomenclaturalTitle})
48
 * or all full names (the strings returned by Person.generateTitle)
49
 * of the persons must exist. A team is a {@link java.util.List list} of persons.
50
 * <P>
51
 * This class corresponds to: <ul>
52
 * <li> Team according to the TDWG ontology
53
 * <li> AgentNames (partially) according to the TCS
54
 * <li> MicroAgent (partially) according to the ABCD schema
55
 * </ul>
56
 *
57
 * @author m.doering
58
 * @version 1.0
59
 * @created 08-Nov-2007 13:06:58
60
 */
61
@XmlAccessorType(XmlAccessType.FIELD)
62
@XmlType(name = "Team", propOrder = {
63
	"protectedNomenclaturalTitleCache",
64
    "teamMembers"
65
})
66
@XmlRootElement(name = "Team")
67
@Entity
68
@Indexed(index = "eu.etaxonomy.cdm.model.agent.AgentBase")
69
@Audited
70
@Configurable
71
public class Team extends TeamOrPersonBase<Team> {
72
	private static final long serialVersionUID = 97640416905934622L;
73
	public static final Logger logger = Logger.getLogger(Team.class);
74

    
75
    @XmlElement(name = "ProtectedNomenclaturalTitleCache")
76
	private boolean protectedNomenclaturalTitleCache = false;
77

    
78
	//An abbreviated name for the team (e. g. in case of nomenclatural authorteams). 
79
    //A non abbreviated name for the team (e. g.
80
	//in case of some bibliographical references)
81
    @XmlElementWrapper(name = "TeamMembers", nillable = true)
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,CascadeType.MERGE})
88
	@Match(MatchMode.MATCH)
89
	private List<Person> teamMembers;
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
	 * Creates a new team instance with a bibliographic and nomenclatural title
101
	 * but without any {@link Person members}. The caches are set to protected.
102
	 */
103
	static public Team NewTitledInstance(String title, String nomTitle){
104
		Team result = new Team();
105
		result.setTitleCache(title, true);
106
		result.setNomenclaturalTitle(nomTitle, true);
107
		return result;
108
	}
109

    
110
	/**
111
	 * Class constructor (including the cache strategy defined in
112
	 * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}).
113
	 */
114
	public Team() {
115
		super();
116
		this.cacheStrategy = TeamDefaultCacheStrategy.NewInstance();
117
		addListenersToMembers();
118
	}
119

    
120
	/**
121
	 * Adds a property change listener to all team members.
122
	 */
123
	private void addListenersToMembers() {
124
		List<Person> members = getTeamMembers();
125
		for (Person member : members){
126
			addListenerForTeamMember(member);
127
		}
128
	}
129

    
130
	/**
131
	 * @return
132
	 */
133
	private void addListenerForTeamMember(Person member) {
134
		PropertyChangeListener listener = new PropertyChangeListener() {
135
			@Override
136
            public void propertyChange(PropertyChangeEvent e) {
137

    
138
// 			   ---- code with no effect below -----
139
//				if (! isProtectedTitleCache()){
140
//					titleCache = titleCache;
141
//				}
142
//				if (! isProtectedNomenclaturalTitleCache()){
143
//					nomenclaturalTitle = nomenclaturalTitle;
144
//				}
145
			}
146
		};
147
		member.addPropertyChangeListener(listener);
148
	}
149

    
150
	/**
151
	 * Returns the list of {@link Person members} belonging to <i>this</i> team.
152
	 * A person may be a member of several distinct teams.
153
	 */
154
	public List<Person> getTeamMembers(){
155
		if(teamMembers == null) {
156
			this.teamMembers = new ArrayList<Person>();
157
		}
158
		return this.teamMembers;
159
	}
160

    
161
	protected void setTeamMembers(List<Person> teamMembers) {
162
		this.teamMembers = teamMembers;
163
		addListenersToMembers();
164
	}
165

    
166
	/**
167
	 * Adds a new {@link Person person} to <i>this</i> team at the end of the members' list.
168
	 *
169
	 * @param  person  the person who should be added to the other team members
170
	 * @see     	   #getTeamMembers()
171
	 * @see 		   Person
172
	 */
173
	public void addTeamMember(Person person){
174
		if (person != null){
175
			getTeamMembers().add(person);
176
			firePropertyChange("teamMember", null, person);
177
			addListenerForTeamMember(person);
178
		}
179
	}
180

    
181
	/**
182
	 * Adds a new {@link Person person} to <i>this</i> team
183
	 * at the given index place of the members' list. If the person is already
184
	 * a member of the list he will be moved to the given index place.
185
	 * The index must be an integer (>=0). If the index is larger than
186
	 * the present number of members the person will be added at the end of the list.
187
	 *
188
	 * @param  person  the person who should be added to the other team members
189
	 * @param  index   the position at which the person should be placed within the members' list (starting with 0)
190
	 * @see     	   #getTeamMembers()
191
	 * @see 		   Person
192
	 */
193
	public void addTeamMember(Person person, int index){
194
		if (person != null){
195
			int oldIndex = getTeamMembers().indexOf(person);
196
			if (oldIndex != -1 ){
197
				getTeamMembers().remove(person);
198
			}
199
			if (index >= getTeamMembers().size()){
200
				index = getTeamMembers().size();
201
			}
202
			getTeamMembers().add(index, person);
203
			addListenerForTeamMember(person);
204
			firePropertyChange("teamMember", null, person);
205
		}
206
	}
207

    
208
	/**
209
	 * Removes one person from the list of members of <i>this</i> team.
210
	 *
211
	 * @param  person  the person who should be deleted from <i>this</i> team
212
	 * @see            #getTeamMembers()
213
	 */
214
	public void removeTeamMember(Person person){
215
		boolean wasMember = getTeamMembers().remove(person);
216
		if (wasMember){
217
			firePropertyChange("teamMember", person, null);
218
		}
219

    
220
	}
221

    
222

    
223
	/**
224
	 * Generates or returns the {@link TeamOrPersonBase#getnomenclaturalTitle() nomenclatural identification} string for <i>this</i> team.
225
	 * This method overrides {@link TeamOrPersonBase#getNomenclaturalTitle() getNomenclaturalTitle}.
226
	 * This string is built with the {@link TeamOrPersonBase#getNomenclaturalTitle() abbreviated names}
227
	 * of all persons belonging to its (ordered) members' list if the flag
228
	 * {@link #protectedNomenclaturalTitleCache protectedNomenclaturalTitleCache} is not set.
229
	 * Otherwise this method returns the present nomenclatural abbreviation.
230
	 * In case the string is generated the cache strategy used is defined in
231
	 * {@link eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy TeamDefaultCacheStrategy}.
232
	 * The result might be kept as nomenclatural abbreviation
233
	 * by using the {@link #setNomenclaturalTitle(String) setNomenclaturalTitle} method.
234
	 *
235
	 * @return  a string which identifies <i>this</i> team for nomenclature
236
	 */
237
	@Override
238
	@Transient
239
	public String getNomenclaturalTitle() {
240
		if (protectedNomenclaturalTitleCache == PROTECTED){
241
			return this.nomenclaturalTitle;
242
		}
243
		if (nomenclaturalTitle == null){
244
			this.nomenclaturalTitle = cacheStrategy.getNomenclaturalTitle(this);
245
		}else{
246
			//as long as team members to not inform the team about changes the cache must be created new each time
247
			nomenclaturalTitle = cacheStrategy.getNomenclaturalTitle(this);
248
		}
249
		return nomenclaturalTitle;
250
	}
251

    
252
	/**
253
	 * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
254
	 * and protects it from overwriting.
255
	 * This method overrides {@link TeamOrPersonBase#setNomenclaturalTitle(String) setNomenclaturalTitle}.
256
	 *
257
	 * @see  #getNomenclaturalTitle()
258
	 * @see  #setNomenclaturalTitle(String, boolean)
259
	 */
260
	@Override
261
	public void setNomenclaturalTitle(String nomenclaturalTitle) {
262
		this.setNomenclaturalTitle(nomenclaturalTitle, PROTECTED);
263
	}
264

    
265
	/**
266
	 * Assigns a {@link TeamOrPersonBase#nomenclaturalTitle nomenclatural identification} string to <i>this</i> team
267
	 * and a protection flag status to this string.
268
	 *
269
	 * @see  #getNomenclaturalTitle()
270
	 */
271
	public void setNomenclaturalTitle(String nomenclaturalTitle, boolean protectedNomenclaturalTitleCache) {
272
		firePropertyChange("nomenclaturalTitle", this.nomenclaturalTitle, nomenclaturalTitle);
273
		this.nomenclaturalTitle = nomenclaturalTitle;
274
		this.protectedNomenclaturalTitleCache = protectedNomenclaturalTitleCache;
275
	}
276

    
277
	/* (non-Javadoc)
278
	 * @see eu.etaxonomy.cdm.model.agent.TeamOrPersonBase#getTitleCache()
279
	 */
280
	@Override
281
	//@Transient //TODO a.kohlbecker remove??
282
	public String getTitleCache() {
283
		isGeneratingTitleCache = true;
284
		String result = "";
285
		if (isProtectedTitleCache()){
286
			result = this.titleCache;
287
		}else{
288
			result = generateTitle();
289
			result = replaceEmptyTitleByNomTitle(result);
290
			result = getTruncatedCache(result);
291
			this.titleCache = result;
292
		}
293
		isGeneratingTitleCache = false;
294
		return result;
295
	}
296

    
297
	public boolean isProtectedNomenclaturalTitleCache() {
298
		return protectedNomenclaturalTitleCache;
299
	}
300

    
301
	public void setProtectedNomenclaturalTitleCache(
302
			boolean protectedNomenclaturalTitleCache) {
303
		this.protectedNomenclaturalTitleCache = protectedNomenclaturalTitleCache;
304
	}
305

    
306
//*********************** CLONE ********************************************************/
307

    
308
	/**
309
	 * Clones <i>this</i> Team. This is a shortcut that enables to create
310
	 * a new instance that differs only slightly from <i>this</i> Team.
311
	 * The corresponding person is cloned.
312
	 *
313
	 * @see eu.etaxonomy.cdm.model.media.IdentifiableMediaEntity#clone()
314
	 * @see java.lang.Object#clone()
315
	 */
316
	@Override
317
	public Object clone() {
318
		try{
319
			Team result = (Team)super.clone();
320
			result.teamMembers = new ArrayList<Person>();
321
			for (Person teamMember: this.teamMembers){
322
				result.addTeamMember(teamMember);
323
			}
324
			//no changes to protectedNomenclaturalTitleCache
325
			return result;
326
		} catch (CloneNotSupportedException e){
327
			logger.warn("Object does not implement cloneable");
328
			e.printStackTrace();
329
			return null;
330
		}
331

    
332

    
333
	}
334

    
335

    
336
}
(8-8/11)