Project

General

Profile

Download (9.37 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.taxon;
11

    
12

    
13
import eu.etaxonomy.cdm.model.description.DescriptionBase;
14
import eu.etaxonomy.cdm.model.description.TaxonDescription;
15
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
16
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
17
import eu.etaxonomy.cdm.model.reference.ReferenceBase;
18

    
19
import org.apache.log4j.Logger;
20
import org.hibernate.annotations.Cascade;
21
import org.hibernate.annotations.CascadeType;
22

    
23
import java.util.*;
24

    
25
import javax.persistence.*;
26

    
27
/**
28
 * An accepted potential taxon defined by the combination of a Name and a sec reference
29
 * {@link Iterable} interface is supported to iterate through taxonomic children
30
 * @author m.doering
31
 * @version 1.0
32
 * @created 08-Nov-2007 13:06:56
33
 */
34
@Entity
35
public class Taxon extends TaxonBase implements Iterable<Taxon>{
36
	static Logger logger = Logger.getLogger(Taxon.class);
37
	private Set<TaxonDescription> descriptions = new HashSet();
38
	// all related synonyms
39
	private Set<SynonymRelationship> synonymRelations = new HashSet();
40
	// all taxa relations with rel.fromTaxon==this
41
	private Set<TaxonRelationship> relationsFromThisTaxon = new HashSet();
42
	// all taxa relations with rel.toTaxon==this
43
	private Set<TaxonRelationship> relationsToThisTaxon = new HashSet();
44
	// shortcut to the taxonomicIncluded (parent) taxon. Managed by the taxonRelations setter
45
	private Taxon taxonomicParentCache;
46

    
47

    
48
	public static Taxon NewInstance(TaxonNameBase taxonName, ReferenceBase sec){
49
		Taxon result = new Taxon();
50
		result.setName(taxonName);
51
		result.setSec(sec);
52
		return result;
53
	}
54
	
55
	//TODO should be private, but still produces Spring init errors
56
	public Taxon(){
57
	}
58

    
59

    
60
	@OneToMany(mappedBy="taxon")
61
	@Cascade({CascadeType.SAVE_UPDATE})
62
	public Set<TaxonDescription> getDescriptions() {
63
		return descriptions;
64
	}
65
	protected void setDescriptions(Set<TaxonDescription> descriptions) {
66
		this.descriptions = descriptions;
67
	}
68
	public void addDescriptions(TaxonDescription description) {
69
		this.descriptions.add(description);
70
	}
71
	public void removeDescriptions(DescriptionBase description) {
72
		this.descriptions.remove(description);
73
	}
74

    
75

    
76
	@OneToMany(mappedBy="acceptedTaxon")
77
	@Cascade({CascadeType.SAVE_UPDATE})
78
	public Set<SynonymRelationship> getSynonymRelations() {
79
		return synonymRelations;
80
	}
81
	protected void setSynonymRelations(Set<SynonymRelationship> synonymRelations) {
82
		this.synonymRelations = synonymRelations;
83
	}
84
	public void addSynonymRelation(SynonymRelationship synonymRelation) {
85
		this.synonymRelations.add(synonymRelation);
86
	}
87
	public void removeSynonymRelation(SynonymRelationship synonymRelation) {
88
		this.synonymRelations.remove(synonymRelation);
89
	}
90
	
91

    
92
	@OneToMany(mappedBy="fromTaxon")
93
	@Cascade({CascadeType.SAVE_UPDATE})
94
	public Set<TaxonRelationship> getRelationsFromThisTaxon() {
95
		return relationsFromThisTaxon;
96
	}
97
	protected void setRelationsFromThisTaxon(
98
			Set<TaxonRelationship> relationsFromThisTaxon) {
99
		this.relationsFromThisTaxon = relationsFromThisTaxon;
100
	}
101

    
102

    
103
	@OneToMany(mappedBy="toTaxon")
104
	@Cascade({CascadeType.SAVE_UPDATE})
105
	public Set<TaxonRelationship> getRelationsToThisTaxon() {
106
		return relationsToThisTaxon;
107
	}
108
	protected void setRelationsToThisTaxon(Set<TaxonRelationship> relationsToThisTaxon) {
109
		this.relationsToThisTaxon = relationsToThisTaxon;
110
	}
111

    
112
	@ManyToOne
113
	// used by hibernate only...
114
	private Taxon getTaxonomicParentCache() {
115
		return taxonomicParentCache;
116
	}
117
	private void setTaxonomicParentCache(Taxon taxonomicParent) {
118
		this.taxonomicParentCache = taxonomicParent;
119
	}
120

    
121
	@Transient
122
	public Set<TaxonRelationship> getTaxonRelations() {
123
		Set<TaxonRelationship> rels = new HashSet();
124
		rels.addAll(getRelationsToThisTaxon());
125
		rels.addAll(getRelationsFromThisTaxon());
126
		return rels;
127
	}
128
	public void removeTaxonRelation(TaxonRelationship rel) {
129
		this.relationsToThisTaxon.remove(rel);
130
		this.relationsFromThisTaxon.remove(rel);
131
		// check if this removes the taxonomical parent. If so, also remove shortcut to the higher taxon
132
		if (rel.getType().equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN()) && rel.getFromTaxon().equals(this)){
133
			this.setTaxonomicParentCache(null);
134
		}
135
		// TODO: remove in related taxon too?
136
	}
137
	public void addTaxonRelation(TaxonRelationship rel) {
138
		if (rel!=null && rel.getType()!=null && !getTaxonRelations().contains(rel)){
139
			if (rel.getFromTaxon().equals(this)){
140
				relationsFromThisTaxon.add(rel);
141
				// also add relation to other taxon object
142
				Taxon toTaxon=rel.getToTaxon();
143
				if (toTaxon!=null){
144
					toTaxon.addTaxonRelation(rel);
145
				}
146
				// check if this sets the taxonomical parent. If so, remember a shortcut to this taxon
147
				if (rel.getType().equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN()) && toTaxon!=null ){
148
					this.setTaxonomicParentCache(rel.getToTaxon());
149
				}
150
			}else if (rel.getToTaxon().equals(this)){
151
				relationsToThisTaxon.add(rel);
152
			}
153
		}
154
	}
155
	public void addTaxonRelation(Taxon toTaxon, TaxonRelationshipType type, ReferenceBase citation, String microcitation) {
156
		TaxonRelationship rel = new TaxonRelationship();
157
		rel.setToTaxon(toTaxon);
158
		rel.setFromTaxon(this);
159
		rel.setType(type);
160
		rel.setCitation(citation);
161
		rel.setCitationMicroReference(microcitation);
162
		this.addTaxonRelation(rel);
163
	}
164
	public void addMisappliedName(Taxon toTaxon, ReferenceBase citation, String microcitation) {
165
		addTaxonRelation(toTaxon, TaxonRelationshipType.MISAPPLIEDNAMEFOR(), citation, microcitation);
166
	}
167

    
168
	
169
	
170
	
171
	@Override
172
	public String generateTitle(){
173
		return this.toString();
174
	}
175

    
176
	@Transient
177
	public void addTaxonomicChild(Taxon child, ReferenceBase citation, String microcitation){
178
		if (child == null){
179
			throw new NullPointerException("Child Taxon is 'null'");
180
		}else{
181
			child.setTaxonomicParent(this, citation, microcitation);
182
		}
183
	}
184
	
185
	/**
186
	 * @return
187
	 */
188
	@Transient
189
	public Taxon getTaxonomicParent() {
190
		return getTaxonomicParentCache();
191
	}
192
	/**
193
	 * @param parent
194
	 * @param citation
195
	 * @param microcitation 
196
	 */
197
	public void setTaxonomicParent(Taxon parent, ReferenceBase citation, String microcitation){
198
		// TODO: remove previously existing parent relationship!!!
199
		if (parent != null){
200
			addTaxonRelation(parent, TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN(),citation,microcitation);
201
		}
202
	}
203

    
204
	/**
205
	 * @return
206
	 */
207
	@Transient
208
	public Set<Taxon> getTaxonomicChildren() {
209
		Set<Taxon> taxa = new HashSet<Taxon>();
210
		for (TaxonRelationship rel: this.getRelationsToThisTaxon()){
211
			TaxonRelationshipType tt = rel.getType();
212
			TaxonRelationshipType incl = TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN(); 
213
			if (tt.equals(incl)){
214
				taxa.add(rel.getFromTaxon());
215
			}
216
		}
217
		return taxa;
218
	}
219
	/**
220
	 * @return
221
	 */
222
	@Transient
223
	public boolean hasTaxonomicChildren(){
224
		for (TaxonRelationship rel: this.getRelationsToThisTaxon()){
225
			if (rel.getType().equals(TaxonRelationshipType.TAXONOMICALLY_INCLUDED_IN())){
226
				return true;
227
			}
228
		}
229
		return false;
230
	}
231

    
232
	
233
	
234
	/*
235
	 * DEALING WITH SYNONYMS
236
	 */
237
	@Transient
238
	public Set<Synonym> getSynonyms(){
239
		Set<Synonym> syns = new HashSet();
240
		for (SynonymRelationship rel: this.getSynonymRelations()){
241
			syns.add(rel.getSynonym());
242
		}
243
		return syns;
244
	}
245
	@Transient
246
	public Set<Synonym> getSynonymsSortedByType(){
247
		// FIXME: need to sort synonyms according to type!!!
248
		return getSynonyms();
249
	}
250
	@Transient
251
	public Set<TaxonNameBase> getSynonymNames(){
252
		Set<TaxonNameBase> names = new HashSet();
253
		for (SynonymRelationship rel: this.getSynonymRelations()){
254
			names.add(rel.getSynonym().getName());
255
		}
256
		return names;
257
	}
258
	/**
259
	 * ass a synonym to this taxon (a taxon can have multiple synonyms that should be proparte synonyms then!)
260
	 * The {@link SynonymRelationship} constructor immediately adds a relationship instance to both 
261
	 * the synonym and taxon instance!
262
	 * @param synonym
263
	 * @param synonymType
264
	 */
265
	public void addSynonym(Synonym synonym, SynonymRelationshipType synonymType){
266
		SynonymRelationship synonymRelationship = new SynonymRelationship(synonym, this, synonymType);
267
	}
268

    
269
	/* (non-Javadoc)
270
	 * @see java.lang.Iterable#iterator()
271
	 */
272
	public Iterator<Taxon> iterator() {
273
		return new TaxonIterator(this.getTaxonomicChildren());
274
	}
275
	/**
276
	 * inner iterator class for the iterable interface
277
	 * @author markus
278
	 *
279
	 */
280
	private class TaxonIterator implements Iterator<Taxon> {
281
		   private Taxon[] items;
282
		   private int i= 0;
283
		   public TaxonIterator(Set<Taxon> items) {
284
		      // check for null being passed in etc.
285
		      this.items= items.toArray(new Taxon[0]);
286
		   }
287
		   // interface implementation
288
		   public boolean hasNext() { return i < items.length; }
289
		   public Taxon next() { return items[i++]; }
290
		   public void remove() { throw new UnsupportedOperationException(); }
291
	}
292
	
293
	@Transient
294
	public HomotypicalGroup getHomotypicGroup(){
295
		return this.getName().getHomotypicalGroup();
296
	}
297
	
298
	@Transient
299
	public List<Synonym> getHomotypicSynonyms(){
300
		return this.getHomotypicGroup().getSynonymsInGroup(this.getSec());
301
	}
302
	
303
	@Transient
304
	public List<HomotypicalGroup> getHeterotypicSynonymyGroups(){
305
		List<HomotypicalGroup> result = new ArrayList();
306
		for (TaxonNameBase n:this.getSynonymNames()){
307
			if (!result.contains(n.getHomotypicalGroup())){
308
				result.add(n.getHomotypicalGroup());
309
			}
310
		}
311
		// TODO: sort list according to date of first published name within each group
312
		return result;
313
	}	
314
}
(4-4/7)