Project

General

Profile

Download (58.7 KB) Statistics
| Branch: | Tag: | Revision:
1 9479da48 Andreas Müller
/**
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.name;
11
12 1cfc54ab Andreas Müller
import java.lang.reflect.Method;
13 396aee74 Andreas Müller
import java.util.HashSet;
14 b24d580a Andreas Kohlbecker
import java.util.List;
15 a48d5a59 Andreas Müller
import java.util.Map;
16 396aee74 Andreas Müller
import java.util.Set;
17
18 33508d06 a.babadshanjan
import javax.persistence.Column;
19 396aee74 Andreas Müller
import javax.persistence.Entity;
20
import javax.persistence.FetchType;
21
import javax.persistence.Inheritance;
22
import javax.persistence.InheritanceType;
23
import javax.persistence.ManyToMany;
24
import javax.persistence.ManyToOne;
25
import javax.persistence.OneToMany;
26 b70a7f94 Andreas Kohlbecker
import javax.persistence.Transient;
27 a641fad9 ben.clark
import javax.validation.constraints.NotNull;
28
import javax.validation.constraints.Size;
29 827f3b3c a.babadshanjan
import javax.xml.bind.annotation.XmlAccessType;
30
import javax.xml.bind.annotation.XmlAccessorType;
31
import javax.xml.bind.annotation.XmlAttribute;
32
import javax.xml.bind.annotation.XmlElement;
33
import javax.xml.bind.annotation.XmlElementWrapper;
34 76b4a40f a.babadshanjan
import javax.xml.bind.annotation.XmlIDREF;
35 9d0d8d15 a.babadshanjan
import javax.xml.bind.annotation.XmlRootElement;
36 76b4a40f a.babadshanjan
import javax.xml.bind.annotation.XmlSchemaType;
37 827f3b3c a.babadshanjan
import javax.xml.bind.annotation.XmlType;
38 9479da48 Andreas Müller
39 396aee74 Andreas Müller
import org.apache.log4j.Logger;
40
import org.hibernate.annotations.Cascade;
41
import org.hibernate.annotations.CascadeType;
42
import org.hibernate.annotations.Index;
43
import org.hibernate.annotations.Table;
44 ee91bcd9 ben.clark
import org.hibernate.envers.Audited;
45 fd7ee7b1 ben.clark
import org.hibernate.search.annotations.Field;
46 a641fad9 ben.clark
import org.hibernate.validator.constraints.NotEmpty;
47 ee91bcd9 ben.clark
import org.springframework.util.ReflectionUtils;
48 396aee74 Andreas Müller
49
import eu.etaxonomy.cdm.model.common.IParsable;
50
import eu.etaxonomy.cdm.model.common.IReferencedEntity;
51
import eu.etaxonomy.cdm.model.common.IRelated;
52
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
53
import eu.etaxonomy.cdm.model.common.RelationshipBase;
54
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
55
import eu.etaxonomy.cdm.model.occurrence.Specimen;
56
import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
57
import eu.etaxonomy.cdm.model.reference.ReferenceBase;
58
import eu.etaxonomy.cdm.model.taxon.Synonym;
59
import eu.etaxonomy.cdm.model.taxon.Taxon;
60
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
61 a48d5a59 Andreas Müller
import eu.etaxonomy.cdm.strategy.cache.name.CacheUpdate;
62 396aee74 Andreas Müller
import eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy;
63 3e1830ec Andreas Müller
import eu.etaxonomy.cdm.strategy.match.IMatchable;
64 57ea5ac1 Andreas Müller
import eu.etaxonomy.cdm.strategy.match.Match;
65
import eu.etaxonomy.cdm.strategy.match.MatchMode;
66 b0b532bd Andreas Müller
import eu.etaxonomy.cdm.strategy.match.Match.ReplaceMode;
67 53befb32 Andreas Müller
import eu.etaxonomy.cdm.strategy.merge.Merge;
68
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
69 5b8e4457 Andreas Müller
import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
70 a641fad9 ben.clark
import eu.etaxonomy.cdm.validation.Level2;
71
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
72 396aee74 Andreas Müller
73 9479da48 Andreas Müller
/**
74 975192f9 m.geoffroy
 * The upmost (abstract) class for scientific taxon names regardless of any
75 c3440568 m.geoffroy
 * particular {@link NomenclaturalCode nomenclature code}. The scientific taxon name does not depend
76 85629348 m.geoffroy
 * on the use made of it in a publication or a treatment
77 09887ea6 m.geoffroy
 * ({@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon concept respectively potential taxon})
78
 * as an {@link eu.etaxonomy.cdm.model.taxon.Taxon "accepted" respectively "correct" (taxon) name}
79
 * or as a {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
80 9e86cd74 m.geoffroy
 * <P>
81
 * This class corresponds partially to: <ul>
82
 * <li> TaxonName according to the TDWG ontology
83
 * <li> ScientificName and CanonicalName according to the TCS
84
 * <li> ScientificName according to the ABCD schema
85
 * </ul>
86 19e7a39e m.geoffroy
 * 
87 9479da48 Andreas Müller
 * @author m.doering
88
 * @version 1.0
89
 * @created 08-Nov-2007 13:06:57
90
 */
91 827f3b3c a.babadshanjan
@XmlAccessorType(XmlAccessType.FIELD)
92 76b4a40f a.babadshanjan
@XmlType(name = "TaxonNameBase", propOrder = {
93 827f3b3c a.babadshanjan
    "appendedPhrase",
94
    "nomenclaturalMicroReference",
95 64c4a14d a.babadshanjan
    "nomenclaturalReference",
96 827f3b3c a.babadshanjan
    "rank",
97 33508d06 a.babadshanjan
    "fullTitleCache",
98
    "protectedFullTitleCache",
99 827f3b3c a.babadshanjan
    "homotypicalGroup",
100 ddae61ce a.babadshanjan
    "typeDesignations",
101 827f3b3c a.babadshanjan
    "relationsFromThisName",
102
    "relationsToThisName",
103 7baa835b a.babadshanjan
    "status",
104 ee91bcd9 ben.clark
    "descriptions",
105
    "taxonBases"
106 827f3b3c a.babadshanjan
})
107 9d0d8d15 a.babadshanjan
@XmlRootElement(name = "TaxonNameBase")
108 9479da48 Andreas Müller
@Entity
109 ee91bcd9 ben.clark
@Audited
110 9479da48 Andreas Müller
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
111 c281e68e Andreas Müller
@Table(appliesTo="TaxonNameBase", indexes = { @Index(name = "taxonNameBaseTitleCacheIndex", columnNames = { "titleCache" }) })
112 3e1830ec Andreas Müller
public abstract class TaxonNameBase<T extends TaxonNameBase<?,?>, S extends INameCacheStrategy> extends IdentifiableEntity<S> implements IReferencedEntity, IParsable, IRelated, IMatchable {
113 961ee94b Andreas Müller
	private static final long serialVersionUID = -4530368639601532116L;
114 b70a7f94 Andreas Kohlbecker
	private static final Logger logger = Logger.getLogger(TaxonNameBase.class);
115 827f3b3c a.babadshanjan
116 33508d06 a.babadshanjan
	@XmlElement(name = "FullTitleCache")
117 ee91bcd9 ben.clark
	@Column(length=330, name="fullTitleCache")
118 b0b532bd Andreas Müller
	@Match(value=MatchMode.CACHE, cacheReplaceMode=ReplaceMode.ALL)
119 a48d5a59 Andreas Müller
	@CacheUpdate(noUpdate ="titleCache")
120 a641fad9 ben.clark
	@NotEmpty(groups = Level2.class)
121
	@Size(max = 330)
122
	protected String fullTitleCache;
123 33508d06 a.babadshanjan
	
124
	//if true titleCache will not be automatically generated/updated
125
	@XmlElement(name = "ProtectedFullTitleCache")
126 a48d5a59 Andreas Müller
	@CacheUpdate(value ="fullTitleCache", noUpdate ="titleCache")
127 a641fad9 ben.clark
	private boolean protectedFullTitleCache;
128 33508d06 a.babadshanjan
	
129 2595daef a.babadshanjan
    @XmlElementWrapper(name = "Descriptions")
130
    @XmlElement(name = "Description")
131 ee91bcd9 ben.clark
    @OneToMany(mappedBy="taxonName", fetch= FetchType.LAZY) 
132
	@Cascade({CascadeType.SAVE_UPDATE})
133 2595daef a.babadshanjan
	private Set<TaxonNameDescription> descriptions = new HashSet<TaxonNameDescription>();
134 71dcc146 Andreas Müller
	
135 76b4a40f a.babadshanjan
    @XmlElement(name = "AppendedPhrase")
136 fd7ee7b1 ben.clark
    @Field(index= org.hibernate.search.annotations.Index.TOKENIZED)
137 a641fad9 ben.clark
    @CacheUpdate(value ="nameCache")
138
    @NullOrNotEmpty
139
    @Size(max = 255)
140
	private String appendedPhrase;
141 827f3b3c a.babadshanjan
	
142 76b4a40f a.babadshanjan
    @XmlElement(name = "NomenclaturalMicroReference")
143 fd7ee7b1 ben.clark
    @Field(index= org.hibernate.search.annotations.Index.TOKENIZED)
144 a641fad9 ben.clark
    @CacheUpdate(noUpdate ="titleCache")
145
    @NullOrNotEmpty
146
    @Size(max = 255)
147
	private String nomenclaturalMicroReference;
148 827f3b3c a.babadshanjan
	
149
    @XmlAttribute
150 a48d5a59 Andreas Müller
    @CacheUpdate(noUpdate ={"titleCache","fullTitleCache"})
151 a641fad9 ben.clark
	private int parsingProblem = 0;
152 827f3b3c a.babadshanjan
	
153 6680df00 Andreas Müller
    @XmlAttribute
154 a48d5a59 Andreas Müller
    @CacheUpdate(noUpdate ={"titleCache","fullTitleCache"})
155 6680df00 Andreas Müller
    private int problemStarts = -1;
156
    
157
    @XmlAttribute
158 a48d5a59 Andreas Müller
    @CacheUpdate(noUpdate ={"titleCache","fullTitleCache"})
159 6680df00 Andreas Müller
    private int problemEnds = -1;
160
    
161 dce4c9cb Andreas Müller
    @XmlElementWrapper(name = "TypeDesignations")
162
    @XmlElement(name = "TypeDesignation")
163 a2312bea a.babadshanjan
    @XmlIDREF
164
    @XmlSchemaType(name = "IDREF")
165 ee91bcd9 ben.clark
    @ManyToMany(fetch = FetchType.LAZY)
166 a641fad9 ben.clark
	//TODO @Cascade({CascadeType.DELETE_ORPHAN})
167
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
168
	@NotNull
169 dce4c9cb Andreas Müller
	private Set<TypeDesignationBase> typeDesignations = new HashSet<TypeDesignationBase>();
170 827f3b3c a.babadshanjan
171 76b4a40f a.babadshanjan
    @XmlElement(name = "HomotypicalGroup")
172 dbff59db a.babadshanjan
    @XmlIDREF
173
    @XmlSchemaType(name = "IDREF")
174 ee91bcd9 ben.clark
    @ManyToOne(fetch = FetchType.LAZY)
175 1ea1c087 ben.clark
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
176 57ea5ac1 Andreas Müller
	@Match(MatchMode.IGNORE)
177 a48d5a59 Andreas Müller
	@CacheUpdate(noUpdate ="titleCache")
178 a641fad9 ben.clark
	@NotNull
179
	private HomotypicalGroup homotypicalGroup;
180 827f3b3c a.babadshanjan
181
    @XmlElementWrapper(name = "RelationsFromThisName")
182
    @XmlElement(name = "RelationFromThisName")
183 ee91bcd9 ben.clark
    @OneToMany(mappedBy="relatedFrom", fetch= FetchType.LAZY)
184 57606ee3 Andreas Müller
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE_ORPHAN})
185 53befb32 Andreas Müller
	@Merge(MergeMode.RELATION)
186 a641fad9 ben.clark
	@NotNull
187 608eada2 Andreas Müller
	private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
188 827f3b3c a.babadshanjan
189
    @XmlElementWrapper(name = "RelationsToThisName")
190
    @XmlElement(name = "RelationToThisName")
191 76b4a40f a.babadshanjan
    @XmlIDREF
192 64c4a14d a.babadshanjan
    @XmlSchemaType(name = "IDREF")
193 ee91bcd9 ben.clark
    @OneToMany(mappedBy="relatedTo", fetch= FetchType.LAZY)
194 57606ee3 Andreas Müller
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE , CascadeType.DELETE_ORPHAN })
195 53befb32 Andreas Müller
	@Merge(MergeMode.RELATION)
196 a641fad9 ben.clark
	@NotNull
197 608eada2 Andreas Müller
	private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
198 827f3b3c a.babadshanjan
199 ee91bcd9 ben.clark
    @XmlElementWrapper(name = "NomenclaturalStatuses")
200 64c4a14d a.babadshanjan
    @XmlElement(name = "NomenclaturalStatus")
201 ee91bcd9 ben.clark
    @OneToMany(fetch= FetchType.LAZY)
202 a641fad9 ben.clark
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE,CascadeType.DELETE,CascadeType.DELETE_ORPHAN})
203
	@NotNull
204 608eada2 Andreas Müller
	private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
205 827f3b3c a.babadshanjan
206 ee91bcd9 ben.clark
    @XmlElementWrapper(name = "TaxonBases")
207
    @XmlElement(name = "TaxonBase")
208
    @XmlIDREF
209
    @XmlSchemaType(name = "IDREF")
210
    @OneToMany(mappedBy="name", fetch= FetchType.LAZY)
211 a641fad9 ben.clark
    @NotNull
212 608eada2 Andreas Müller
	private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
213 33508d06 a.babadshanjan
    
214 76b4a40f a.babadshanjan
    @XmlElement(name = "Rank")
215
	@XmlIDREF
216
	@XmlSchemaType(name = "IDREF")
217 4208745a ben.clark
	@ManyToOne(fetch = FetchType.EAGER)
218 a48d5a59 Andreas Müller
	@CacheUpdate(value ="nameCache")
219 a641fad9 ben.clark
	@NotNull
220
	private Rank rank;
221 827f3b3c a.babadshanjan
222 ee91bcd9 ben.clark
	@XmlElement(name = "NomenclaturalReference")
223 64c4a14d a.babadshanjan
    @XmlIDREF
224
    @XmlSchemaType(name = "IDREF")
225 ee91bcd9 ben.clark
    @ManyToOne(fetch = FetchType.LAZY)
226
	@Cascade({CascadeType.SAVE_UPDATE})
227 a48d5a59 Andreas Müller
	@CacheUpdate(noUpdate ="titleCache")
228 a641fad9 ben.clark
	private ReferenceBase nomenclaturalReference;
229 1cfc54ab Andreas Müller
	
230 2a486d28 Andreas Müller
// ************* CONSTRUCTORS *************/	
231 12655d36 m.geoffroy
	/** 
232 85629348 m.geoffroy
	 * Class constructor: creates a new empty taxon name.
233 12655d36 m.geoffroy
	 * 
234
	 * @see #TaxonNameBase(Rank)
235
	 * @see #TaxonNameBase(HomotypicalGroup)
236
	 * @see #TaxonNameBase(Rank, HomotypicalGroup)
237
	 */
238 9479da48 Andreas Müller
	public TaxonNameBase() {
239 ee91bcd9 ben.clark
		super();
240 9479da48 Andreas Müller
	}
241 12655d36 m.geoffroy
	/** 
242 85629348 m.geoffroy
	 * Class constructor: creates a new taxon name
243 09887ea6 m.geoffroy
	 * only containing its {@link Rank rank}.
244 12655d36 m.geoffroy
	 * 
245 b9d0e8d2 m.geoffroy
	 * @param  rank  the rank to be assigned to <i>this</i> taxon name
246 6a9737e8 m.geoffroy
	 * @see    		 #TaxonNameBase()
247
	 * @see    		 #TaxonNameBase(HomotypicalGroup)
248
	 * @see    		 #TaxonNameBase(Rank, HomotypicalGroup)
249 12655d36 m.geoffroy
	 */
250 9479da48 Andreas Müller
	public TaxonNameBase(Rank rank) {
251 b18c6379 Andreas Müller
		this(rank, null);
252
	}
253 12655d36 m.geoffroy
	/** 
254 85629348 m.geoffroy
	 * Class constructor: creates a new taxon name
255 9dac7f49 m.geoffroy
	 * only containing its {@link HomotypicalGroup homotypical group}.
256 85629348 m.geoffroy
	 * The new taxon name will be also added to the set of taxon names
257 740cb3b5 m.geoffroy
	 * belonging to this homotypical group.
258 12655d36 m.geoffroy
	 * 
259 b9d0e8d2 m.geoffroy
	 * @param  homotypicalGroup  the homotypical group to which <i>this</i> taxon name belongs
260 6a9737e8 m.geoffroy
	 * @see    					 #TaxonNameBase()
261
	 * @see    					 #TaxonNameBase(Rank)
262
	 * @see    					 #TaxonNameBase(Rank, HomotypicalGroup)
263 12655d36 m.geoffroy
	 */
264 b18c6379 Andreas Müller
	public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
265
		this(null, homotypicalGroup);
266
	}
267 12655d36 m.geoffroy
	/** 
268 85629348 m.geoffroy
	 * Class constructor: creates a new taxon name
269 09887ea6 m.geoffroy
	 * only containing its {@link Rank rank} and
270 9dac7f49 m.geoffroy
	 * its {@link HomotypicalGroup homotypical group}.
271 740cb3b5 m.geoffroy
	 * The new taxon name will be also added to the set of taxon names
272
	 * belonging to this homotypical group.
273 12655d36 m.geoffroy
	 * 
274 6a9737e8 m.geoffroy
	 * @param  rank  			 the rank to be assigned to <i>this</i> taxon name
275 b9d0e8d2 m.geoffroy
	 * @param  homotypicalGroup  the homotypical group to which <i>this</i> taxon name belongs
276 6a9737e8 m.geoffroy
	 * @see    					 #TaxonNameBase()
277
	 * @see    					 #TaxonNameBase(Rank)
278
	 * @see    					 #TaxonNameBase(HomotypicalGroup)
279 12655d36 m.geoffroy
	 */
280 b18c6379 Andreas Müller
	public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
281 9479da48 Andreas Müller
		super();
282
		this.setRank(rank);
283 b18c6379 Andreas Müller
		if (homotypicalGroup == null){
284
			homotypicalGroup = new HomotypicalGroup();
285
		}
286
		homotypicalGroup.addTypifiedName(this);
287 9479da48 Andreas Müller
	}
288 2a486d28 Andreas Müller
	
289 a48d5a59 Andreas Müller
	abstract protected Map<String, java.lang.reflect.Field> getAllFields();
290
	
291 2a486d28 Andreas Müller
//********* METHODS **************************************/
292 9017e2de Andreas Müller
	
293 12655d36 m.geoffroy
	/**
294 b9d0e8d2 m.geoffroy
	 * Returns the boolean value "false" since the components of <i>this</i> taxon name
295 eb7e638a m.geoffroy
	 * cannot follow the rules of a corresponding {@link NomenclaturalCode nomenclatural code}
296
	 * which is not defined for this class. The nomenclature code depends on
297 12655d36 m.geoffroy
	 * the concrete name subclass ({@link BacterialName BacterialName},
298
	 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
299
	 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName}) 
300 eb7e638a m.geoffroy
	 * to which a taxon name belongs.
301 12655d36 m.geoffroy
	 *  
302 eb7e638a m.geoffroy
	 * @return  false
303 12655d36 m.geoffroy
	 */
304 b70a7f94 Andreas Kohlbecker
	@Transient
305 9479da48 Andreas Müller
	public abstract boolean isCodeCompliant();
306
	
307 33508d06 a.babadshanjan
	public abstract String generateFullTitle();
308 9479da48 Andreas Müller
309 a48d5a59 Andreas Müller
	
310
311
	@Transient
312
	public List<Object> getTaggedName(){
313
		return getCacheStrategy().getTaggedName(this);
314
	}
315
	
316 b70a7f94 Andreas Kohlbecker
	@Transient
317 33508d06 a.babadshanjan
	public String getFullTitleCache(){
318
		if (protectedFullTitleCache){
319
			return this.fullTitleCache;			
320
		}
321 a48d5a59 Andreas Müller
		if (fullTitleCache == null ){
322
			this.fullTitleCache = getTruncatedCache(generateFullTitle());
323 33508d06 a.babadshanjan
		}
324
		return fullTitleCache;
325
	}
326
327 a48d5a59 Andreas Müller
	
328 33508d06 a.babadshanjan
    public void setFullTitleCache(String fullTitleCache){
329
		setFullTitleCache(fullTitleCache, PROTECTED);
330
	}
331
	
332
	public void setFullTitleCache(String fullTitleCache, boolean protectCache){
333 a48d5a59 Andreas Müller
		fullTitleCache = getTruncatedCache(fullTitleCache);
334 33508d06 a.babadshanjan
		this.fullTitleCache = fullTitleCache;
335
		this.setProtectedFullTitleCache(protectCache);
336
	}
337 a48d5a59 Andreas Müller
338 33508d06 a.babadshanjan
	
339
	public boolean isProtectedFullTitleCache() {
340
		return protectedFullTitleCache;
341
	}
342
343
	public void setProtectedFullTitleCache(boolean protectedFullTitleCache) {
344
		this.protectedFullTitleCache = protectedFullTitleCache;
345
	}
346
	
347 12655d36 m.geoffroy
	/** 
348
	 * Returns the set of all {@link NameRelationship name relationships}
349 b9d0e8d2 m.geoffroy
	 * in which <i>this</i> taxon name is involved. A taxon name can be both source
350 12655d36 m.geoffroy
	 * in some name relationships or target in some others.
351
	 *  
352 09487e73 m.geoffroy
	 * @see    #getRelationsToThisName()
353
	 * @see    #getRelationsFromThisName()
354
	 * @see    #addNameRelationship(NameRelationship)
355 12655d36 m.geoffroy
	 * @see    #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
356
	 * @see    #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
357
	 */
358 b70a7f94 Andreas Kohlbecker
	@Transient
359 9479da48 Andreas Müller
	public Set<NameRelationship> getNameRelations() {
360 6ecda5d2 m.doering
		Set<NameRelationship> rels = new HashSet<NameRelationship>();
361
		rels.addAll(getRelationsFromThisName());
362
		rels.addAll(getRelationsToThisName());
363
		return rels;
364
	}
365 b92a6173 a.babadshanjan
	
366 6ecda5d2 m.doering
	/**
367 b9d0e8d2 m.geoffroy
	 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from <i>this</i> taxon name to another taxon name
368
	 * and adds it both to the set of {@link #getRelationsFromThisName() relations from <i>this</i> taxon name} and
369 12655d36 m.geoffroy
	 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
370
	 * 
371
	 * @param toName		  the taxon name of the target for this new name relationship
372
	 * @param type			  the type of this new name relationship
373
	 * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
374 09487e73 m.geoffroy
	 * @see    				  #getRelationsToThisName()
375
	 * @see    				  #getNameRelations()
376 12655d36 m.geoffroy
	 * @see    				  #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
377
	 * @see    				  #addNameRelationship(NameRelationship)
378 6ecda5d2 m.doering
	 */
379
	public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
380 b30dfca2 Andreas Müller
		addRelationshipToName(toName, type, null, null, ruleConsidered);
381
		//		NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
382 6ecda5d2 m.doering
	}
383 21f31bf8 Andreas Müller
	
384 b30dfca2 Andreas Müller
	/**
385
	 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from <i>this</i> taxon name to another taxon name
386
	 * and adds it both to the set of {@link #getRelationsFromThisName() relations from <i>this</i> taxon name} and
387
	 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
388
	 * 
389
	 * @param toName		  the taxon name of the target for this new name relationship
390
	 * @param type			  the type of this new name relationship
391
	 * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
392
	 * @see    				  #getRelationsToThisName()
393
	 * @see    				  #getNameRelations()
394
	 * @see    				  #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
395
	 * @see    				  #addNameRelationship(NameRelationship)
396
	 */
397
public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
398
		if (toName == null){
399
			throw new NullPointerException("Null is not allowed as name for a name relationship");
400
		}
401 21f31bf8 Andreas Müller
		NameRelationship rel = new NameRelationship(toName, this, type, citation, microCitation, ruleConsidered);
402 b30dfca2 Andreas Müller
//		if (type.isBasionymRelation() || type.isReplacedSynonymRelation()){
403
//			this.getHomotypicalGroup().merge(toName.getHomotypicalGroup());
404
//		}
405 21f31bf8 Andreas Müller
	}
406
	
407 12655d36 m.geoffroy
	/**
408 b9d0e8d2 m.geoffroy
	 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to <i>this</i> taxon name
409
	 * and adds it both to the set of {@link #getRelationsToThisName() relations to <i>this</i> taxon name} and
410 12655d36 m.geoffroy
	 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
411
	 * 
412
	 * @param fromName		  the taxon name of the source for this new name relationship
413
	 * @param type			  the type of this new name relationship
414
	 * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
415 b30dfca2 Andreas Müller
	 * @param citation		  the reference in which this relation was described
416
	 * @param microCitation	  the reference detail for this relation (e.g. page) 
417 09487e73 m.geoffroy
	 * @see    				  #getRelationsFromThisName()
418
	 * @see    				  #getNameRelations()
419 12655d36 m.geoffroy
	 * @see    				  #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
420
	 * @see    				  #addNameRelationship(NameRelationship)
421
	 */
422 4dd3e141 m.doering
	public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
423 b30dfca2 Andreas Müller
		fromName.addRelationshipToName(this, type, null, null, ruleConsidered);
424
//		NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
425 4dd3e141 m.doering
	}
426 b30dfca2 Andreas Müller
	/**
427
	 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to <i>this</i> taxon name
428
	 * and adds it both to the set of {@link #getRelationsToThisName() relations to <i>this</i> taxon name} and
429
	 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
430
	 * 
431
	 * @param fromName		  the taxon name of the source for this new name relationship
432
	 * @param type			  the type of this new name relationship
433
	 * @param ruleConsidered  the string which specifies the rule on which this name relationship is based
434
	 * @param citation		  the reference in which this relation was described
435
	 * @param microCitation	  the reference detail for this relation (e.g. page) 
436
	 * @see    				  #getRelationsFromThisName()
437
	 * @see    				  #getNameRelations()
438
	 * @see    				  #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
439
	 * @see    				  #addNameRelationship(NameRelationship)
440
	 */
441 21f31bf8 Andreas Müller
	public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, ReferenceBase citation, String microCitation, String ruleConsidered){
442 b30dfca2 Andreas Müller
		fromName.addRelationshipToName(this, type, citation, microCitation, ruleConsidered);
443 21f31bf8 Andreas Müller
	}
444
445 12655d36 m.geoffroy
	/**
446
	 * Adds an existing {@link NameRelationship name relationship} either to the set of
447 b9d0e8d2 m.geoffroy
	 * {@link #getRelationsToThisName() relations to <i>this</i> taxon name} or to the set of
448
	 * {@link #getRelationsFromThisName() relations from <i>this</i> taxon name}. If neither the
449
	 * source nor the target of the name relationship match with <i>this</i> taxon name
450 12655d36 m.geoffroy
	 * no addition will be carried out.
451
	 * 
452 b9d0e8d2 m.geoffroy
	 * @param rel  the name relationship to be added to one of <i>this</i> taxon name's name relationships sets
453 09487e73 m.geoffroy
	 * @see    	   #getNameRelations()
454 12655d36 m.geoffroy
	 * @see    	   #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
455
	 * @see    	   #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
456
	 */
457 6ecda5d2 m.doering
	protected void addNameRelationship(NameRelationship rel) {
458
		if (rel!=null && rel.getToName().equals(this)){
459
			this.relationsToThisName.add(rel);
460
		}else if(rel!=null && rel.getFromName().equals(this)){
461
			this.relationsFromThisName.add(rel);			
462
		}else{
463 b30dfca2 Andreas Müller
			throw new RuntimeException("NameRelationship is either null or the relationship does not reference this name");
464 6ecda5d2 m.doering
		}
465 9479da48 Andreas Müller
	}
466 12655d36 m.geoffroy
	/** 
467
	 * Removes one {@link NameRelationship name relationship} from one of both sets of
468 b9d0e8d2 m.geoffroy
	 * {@link #getNameRelations() name relationships} in which <i>this</i> taxon name is involved.
469 09487e73 m.geoffroy
	 * The name relationship will also be removed from one of both sets belonging
470
	 * to the second taxon name involved. Furthermore the fromName and toName
471
	 * attributes of the name relationship object will be nullified. 
472 12655d36 m.geoffroy
	 *
473
	 * @param  nameRelation  the name relationship which should be deleted from one of both sets
474 6a9737e8 m.geoffroy
	 * @see    				 #getNameRelations()
475 12655d36 m.geoffroy
	 */
476 6ecda5d2 m.doering
	public void removeNameRelationship(NameRelationship nameRelation) {
477 b92a6173 a.babadshanjan
		
478
		TaxonNameBase fromName = nameRelation.getFromName();
479
		TaxonNameBase toName = nameRelation.getToName();
480
481
		if (nameRelation != null) {
482
			nameRelation.setToName(null);
483
			nameRelation.setFromName(null);
484
		}
485
		
486
		if (fromName != null) {
487
			fromName.removeNameRelationship(nameRelation);
488
		}
489
		
490
		if (toName != null) {
491
			toName.removeNameRelationship(nameRelation);
492
		}
493
		
494
		this.relationsToThisName.remove(nameRelation);
495
		this.relationsFromThisName.remove(nameRelation);
496
	}
497
		
498 30424f60 Andreas Müller
	public void removeRelationToTaxonName(TaxonNameBase toTaxonName) {
499 b92a6173 a.babadshanjan
		Set<NameRelationship> nameRelationships = new HashSet<NameRelationship>();
500
//		nameRelationships.addAll(this.getNameRelations());
501
		nameRelationships.addAll(this.getRelationsFromThisName());
502
		nameRelationships.addAll(this.getRelationsToThisName());
503
		for(NameRelationship nameRelationship : nameRelationships) {
504
			// remove name relationship from this side 
505 30424f60 Andreas Müller
			if (nameRelationship.getFromName().equals(this) && nameRelationship.getToName().equals(toTaxonName)) {
506
				this.removeNameRelationship(nameRelationship);
507 b92a6173 a.babadshanjan
			}
508
		}
509
	}
510 30424f60 Andreas Müller
511 6ecda5d2 m.doering
	
512 b3262b1b m.geoffroy
	/**
513
	 * Does exactly the same as the addNameRelationship method provided that
514
	 * the given relationship is a name relationship.
515
	 * 
516 b9d0e8d2 m.geoffroy
	 * @param relation  the relationship to be added to one of <i>this</i> taxon name's name relationships sets
517 b3262b1b m.geoffroy
	 * @see    	   		#addNameRelationship(NameRelationship)
518
	 * @see    	   		#getNameRelations()
519
	 * @see    	   		NameRelationship
520 09887ea6 m.geoffroy
	 * @see    	   		eu.etaxonomy.cdm.model.common.RelationshipBase
521 b3262b1b m.geoffroy
	 */
522 705e0850 Andreas Müller
	public void addRelationship(RelationshipBase relation) {
523
		if (relation instanceof NameRelationship){
524
			addNameRelationship((NameRelationship)relation);
525 b30dfca2 Andreas Müller
			NameRelationshipType type = (NameRelationshipType)relation.getType();
526
			if (type != null && ( type.isBasionymRelation() || type.isReplacedSynonymRelation() ) ){
527 d27ee9b1 Andreas Müller
				TaxonNameBase fromName = ((NameRelationship)relation).getFromName();
528
				TaxonNameBase toName = ((NameRelationship)relation).getToName();
529 30424f60 Andreas Müller
				fromName.mergeHomotypicGroups(toName);
530 d27ee9b1 Andreas Müller
			}		
531 705e0850 Andreas Müller
		}else{
532 d27ee9b1 Andreas Müller
			logger.warn("Relationship not of type NameRelationship!");
533 b30dfca2 Andreas Müller
			throw new IllegalArgumentException("Relationship not of type NameRelationship");
534 705e0850 Andreas Müller
		}
535 7ebeb288 Andreas Müller
	}
536
537
	
538 09487e73 m.geoffroy
	/** 
539
	 * Returns the set of all {@link NameRelationship name relationships}
540 b9d0e8d2 m.geoffroy
	 * in which <i>this</i> taxon name is involved as a source.
541 09487e73 m.geoffroy
	 *  
542
	 * @see    #getNameRelations()
543
	 * @see    #getRelationsToThisName()
544
	 * @see    #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
545
	 */
546 6ecda5d2 m.doering
	public Set<NameRelationship> getRelationsFromThisName() {
547 a641fad9 ben.clark
		if(relationsFromThisName == null) {
548
			this.relationsFromThisName = new HashSet<NameRelationship>();
549
		}
550 6ecda5d2 m.doering
		return relationsFromThisName;
551 9479da48 Andreas Müller
	}
552 ee91bcd9 ben.clark
553 09487e73 m.geoffroy
	/** 
554
	 * Returns the set of all {@link NameRelationship name relationships}
555 b9d0e8d2 m.geoffroy
	 * in which <i>this</i> taxon name is involved as a target.
556 09487e73 m.geoffroy
	 *  
557
	 * @see    #getNameRelations()
558
	 * @see    #getRelationsFromThisName()
559
	 * @see    #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
560
	 */
561 6ecda5d2 m.doering
	public Set<NameRelationship> getRelationsToThisName() {
562 a641fad9 ben.clark
		if(relationsToThisName == null) {
563
			this.relationsToThisName = new HashSet<NameRelationship>();
564
		}
565 6ecda5d2 m.doering
		return relationsToThisName;
566 9479da48 Andreas Müller
	}
567
	
568 09487e73 m.geoffroy
	/** 
569
	 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
570 b9d0e8d2 m.geoffroy
	 * to <i>this</i> taxon name according to its corresponding nomenclature code.
571 09487e73 m.geoffroy
	 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
572
	 * and the nomenclatural code rule considered.
573
	 *
574
	 * @see     NomenclaturalStatus
575
	 * @see     NomenclaturalStatusType
576
	 */
577 9479da48 Andreas Müller
	public Set<NomenclaturalStatus> getStatus() {
578 a641fad9 ben.clark
		if(status == null) {
579
			this.status = new HashSet<NomenclaturalStatus>();
580
		}
581 9479da48 Andreas Müller
		return status;
582
	}
583 ee91bcd9 ben.clark
584 09487e73 m.geoffroy
	/** 
585
	 * Adds a new {@link NomenclaturalStatus nomenclatural status}
586 b9d0e8d2 m.geoffroy
	 * to <i>this</i> taxon name's set of nomenclatural status.
587 09487e73 m.geoffroy
	 *
588
	 * @param  nomStatus  the nomenclatural status to be added
589
	 * @see 			  #getStatus()
590
	 */
591 025f3199 Andreas Müller
	public void addStatus(NomenclaturalStatus nomStatus) {
592
		this.status.add(nomStatus);
593 9479da48 Andreas Müller
	}
594 ee91bcd9 ben.clark
	
595 09487e73 m.geoffroy
	/** 
596 b9d0e8d2 m.geoffroy
	 * Removes one element from the set of nomenclatural status of <i>this</i> taxon name.
597 09487e73 m.geoffroy
	 * Type and ruleConsidered attributes of the nomenclatural status object
598
	 * will be nullified.
599
	 *
600 b9d0e8d2 m.geoffroy
	 * @param  nomStatus  the nomenclatural status of <i>this</i> taxon name which should be deleted
601 09487e73 m.geoffroy
	 * @see     		  #getStatus()
602
	 */
603 025f3199 Andreas Müller
	public void removeStatus(NomenclaturalStatus nomStatus) {
604 09487e73 m.geoffroy
		//TODO to be implemented?
605
		logger.warn("not yet fully implemented?");
606 025f3199 Andreas Müller
		this.status.remove(nomStatus);
607 9479da48 Andreas Müller
	}
608
609 5c19d7f0 Andreas Müller
	
610
	/**
611 09887ea6 m.geoffroy
	 * Indicates whether <i>this</i> taxon name is a {@link NameRelationshipType#BASIONYM() basionym}
612
	 * or a {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym}
613 abc6aceb m.geoffroy
	 * of any other taxon name. Returns "true", if a basionym or a replaced 
614 09887ea6 m.geoffroy
	 * synonym {@link NameRelationship relationship} from <i>this</i> taxon name to another taxon name exists,
615 b9d0e8d2 m.geoffroy
	 * false otherwise (also in case <i>this</i> taxon name is the only one in the
616 09487e73 m.geoffroy
	 * homotypical group).
617 5c19d7f0 Andreas Müller
	 */
618 b70a7f94 Andreas Kohlbecker
	@Transient
619 5c19d7f0 Andreas Müller
	public boolean isOriginalCombination(){
620
		Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
621
		for (NameRelationship relation : relationsFromThisName) {
622 30424f60 Andreas Müller
			if (relation.getType().isBasionymRelation() ||
623
					relation.getType().isReplacedSynonymRelation()) {
624 5c19d7f0 Andreas Müller
				return true;
625
			}
626
		}
627
		return false;
628
	}
629
	
630 09487e73 m.geoffroy
	/**
631 09887ea6 m.geoffroy
	 * Returns the taxon name which is the {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
632 09487e73 m.geoffroy
	 * The basionym of a taxon name is its epithet-bringing synonym.
633 09887ea6 m.geoffroy
	 * For instance <i>Pinus abies</i> L. was published by Linnaeus and the botanist
634 b9d0e8d2 m.geoffroy
	 * Karsten transferred later <i>this</i> taxon to the genus Picea. Therefore,
635 09887ea6 m.geoffroy
	 * <i>Pinus abies</i> L. is the basionym of the new combination <i>Picea abies</i> (L.) H. Karst.
636 30424f60 Andreas Müller
	 * 
637
	 * If more than one basionym exists one is choosen at radom.
638
	 * 
639
	 * If no basionym exists null is returned.
640 09487e73 m.geoffroy
	 */
641 b70a7f94 Andreas Kohlbecker
	@Transient
642 30424f60 Andreas Müller
	public TaxonNameBase getBasionym(){
643
		Set<TaxonNameBase> basionyms = getBasionyms();
644
		if (basionyms.size() == 0){
645
			return null;
646
		}else{
647
			return basionyms.iterator().next();
648
		}
649
	}
650
	
651
	/**
652
	 * Returns the set of taxon names which are the {@link NameRelationshipType#BASIONYM() basionyms} of <i>this</i> taxon name.
653
	 * The basionym of a taxon name is its epithet-bringing synonym.
654
	 * For instance <i>Pinus abies</i> L. was published by Linnaeus and the botanist
655
	 * Karsten transferred later <i>this</i> taxon to the genus Picea. Therefore,
656
	 * <i>Pinus abies</i> L. is the basionym of the new combination <i>Picea abies</i> (L.) H. Karst.
657
	 */
658
	@Transient
659
	public Set<TaxonNameBase> getBasionyms(){
660
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
661
		Set<NameRelationship> rels = this.getRelationsToThisName();
662
		for (NameRelationship rel : rels){
663
			if (rel.getType().isBasionymRelation()){
664
				TaxonNameBase basionym = rel.getFromName();
665
				result.add(basionym);
666
			}
667
		}
668
		return result;
669 9479da48 Andreas Müller
	}
670 30424f60 Andreas Müller
	
671 09487e73 m.geoffroy
	/**
672 09887ea6 m.geoffroy
	 * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
673
	 * The basionym {@link NameRelationship relationship} will be added to <i>this</i> taxon name
674 09487e73 m.geoffroy
	 * and to the basionym. The basionym cannot have itself a basionym.
675 09887ea6 m.geoffroy
	 * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
676
	 * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
677
	 * 
678
	 * @param  basionym		the taxon name to be set as the basionym of <i>this</i> taxon name
679
	 * @see  				#getBasionym()
680
	 * @see  				#addBasionym(TaxonNameBase, String)
681 09487e73 m.geoffroy
	 */
682 d27ee9b1 Andreas Müller
	public void addBasionym(T basionym){
683 21f31bf8 Andreas Müller
		addBasionym(basionym, null, null, null);
684 6ecda5d2 m.doering
	}
685 09487e73 m.geoffroy
	/**
686 09887ea6 m.geoffroy
	 * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name
687 09487e73 m.geoffroy
	 * and keeps the nomenclatural rule considered for it. The basionym
688 09887ea6 m.geoffroy
	 * {@link NameRelationship relationship} will be added to <i>this</i> taxon name and to the basionym.
689
	 * The basionym cannot have itself a basionym.
690
	 * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
691
	 * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
692
	 * 
693
	 * @param  basionym			the taxon name to be set as the basionym of <i>this</i> taxon name
694
	 * @param  ruleConsidered	the string identifying the nomenclatural rule
695
	 * @see  					#getBasionym()
696
	 * @see  					#addBasionym(TaxonNameBase)
697 09487e73 m.geoffroy
	 */
698 21f31bf8 Andreas Müller
	public void addBasionym(T basionym, ReferenceBase citation, String microcitation, String ruleConsidered){
699 d27ee9b1 Andreas Müller
		if (basionym != null){
700 21f31bf8 Andreas Müller
			basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), citation, microcitation, ruleConsidered);
701 d27ee9b1 Andreas Müller
		}
702
	}
703
	
704 b30dfca2 Andreas Müller
	/**
705
	 * Assigns a taxon name as {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym} of <i>this</i> taxon name
706
	 * and keeps the nomenclatural rule considered for it. The replaced synonym
707
	 * {@link NameRelationship relationship} will be added to <i>this</i> taxon name and to the replaced synonym.
708
	 * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the replaced synonym
709
	 * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
710
	 * 
711
	 * @param  basionym			the taxon name to be set as the basionym of <i>this</i> taxon name
712
	 * @param  ruleConsidered	the string identifying the nomenclatural rule
713
	 * @see  					#getBasionym()
714
	 * @see  					#addBasionym(TaxonNameBase)
715
	 */
716
	//TODO: Check if true: The replaced synonym cannot have itself a replaced synonym (?).
717
	public void addReplacedSynonym(T replacedSynonym, ReferenceBase citation, String microcitation, String ruleConsidered){
718
		if (replacedSynonym != null){
719
			replacedSynonym.addRelationshipToName(this, NameRelationshipType.REPLACED_SYNONYM(), citation, microcitation, ruleConsidered);
720
		}
721
	}
722
	
723 09887ea6 m.geoffroy
	/** 
724
	 * Removes the {@link NameRelationshipType#BASIONYM() basionym} {@link NameRelationship relationship} from the set of
725
	 * {@link #getRelationsToThisName() name relationships to} <i>this</i> taxon name. The same relationhip will be
726
	 * removed from the set of {@link #getRelationsFromThisName() name relationships from} the taxon name
727
	 * previously used as basionym.
728
	 *
729
	 * @see   #getBasionym()
730
	 * @see   #addBasionym(TaxonNameBase)
731
	 */
732 30424f60 Andreas Müller
	public void removeBasionyms(){
733
		Set<NameRelationship> removeRelations = new HashSet<NameRelationship>();
734
		for (NameRelationship nameRelation : this.getRelationsToThisName()){
735
			if (nameRelation.getType().isBasionymRelation()){
736
				removeRelations.add(nameRelation);
737
			}
738
		}
739
		// Removing relations from a set through which we are iterating causes a
740
		// ConcurrentModificationException. Therefore, we delete the targeted
741
		// relations in a second step.
742
		for (NameRelationship relation : removeRelations){
743
			this.removeNameRelationship(relation);
744
		}
745 9479da48 Andreas Müller
	}
746
	
747 8eebe79d m.geoffroy
	/** 
748 b9d0e8d2 m.geoffroy
	 * Returns the taxonomic {@link Rank rank} of <i>this</i> taxon name.
749 8eebe79d m.geoffroy
	 *
750
	 * @see 	Rank
751
	 */
752 9479da48 Andreas Müller
	public Rank getRank(){
753
		return this.rank;
754
	}
755 ee91bcd9 ben.clark
	
756 8eebe79d m.geoffroy
	/**
757
	 * @see  #getRank()
758
	 */
759 9479da48 Andreas Müller
	public void setRank(Rank rank){
760
		this.rank = rank;
761
	}
762
763 8eebe79d m.geoffroy
	/** 
764 09887ea6 m.geoffroy
	 * Returns the {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} of <i>this</i> taxon name.
765 8eebe79d m.geoffroy
	 * The nomenclatural reference is here meant to be the one publication
766 b9d0e8d2 m.geoffroy
	 * <i>this</i> taxon name was originally published in while fulfilling the formal
767 a7d9a8c1 m.geoffroy
	 * requirements as specified by the corresponding {@link NomenclaturalCode nomenclatural code}.
768 8eebe79d m.geoffroy
	 *
769 09887ea6 m.geoffroy
	 * @see 	eu.etaxonomy.cdm.model.reference.INomenclaturalReference
770
	 * @see 	eu.etaxonomy.cdm.model.reference.ReferenceBase
771 8eebe79d m.geoffroy
	 */
772 b70a7f94 Andreas Kohlbecker
	public ReferenceBase getNomenclaturalReference(){
773
		return this.nomenclaturalReference;
774 9479da48 Andreas Müller
	}
775 8eebe79d m.geoffroy
	/**
776 09887ea6 m.geoffroy
	 * Assigns a {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} to <i>this</i> taxon name.
777
	 * The corresponding {@link eu.etaxonomy.cdm.model.reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
778 8eebe79d m.geoffroy
	 * as it is obviously used for nomenclatural purposes.
779
	 *
780 b70a7f94 Andreas Kohlbecker
	 * @throws IllegalArgumentException if parameter <code>nomenclaturalReference</code> is not assignable from {@link INomenclaturalReference}
781 8eebe79d m.geoffroy
	 * @see  #getNomenclaturalReference()
782
	 */
783 b70a7f94 Andreas Kohlbecker
	public void setNomenclaturalReference(ReferenceBase nomenclaturalReference){
784
		if(nomenclaturalReference != null){
785
			if(!INomenclaturalReference.class.isAssignableFrom(nomenclaturalReference.getClass())){
786
				throw new IllegalArgumentException("Parameter nomenclaturalReference is not assignable from INomenclaturalReference");
787
			}
788
			this.nomenclaturalReference = (ReferenceBase)nomenclaturalReference;
789
		} else {
790
			this.nomenclaturalReference = null;
791
		}
792 9479da48 Andreas Müller
	}
793
794 8eebe79d m.geoffroy
	/** 
795 b9d0e8d2 m.geoffroy
	 * Returns the appended phrase string assigned to <i>this</i> taxon name.
796 8eebe79d m.geoffroy
	 * The appended phrase is a non-atomised addition to a name. It is
797
	 * not ruled by a nomenclatural code.
798
	 */
799 9479da48 Andreas Müller
	public String getAppendedPhrase(){
800
		return this.appendedPhrase;
801
	}
802 ee91bcd9 ben.clark
	
803 8eebe79d m.geoffroy
	/**
804
	 * @see  #getAppendedPhrase()
805
	 */
806 9479da48 Andreas Müller
	public void setAppendedPhrase(String appendedPhrase){
807
		this.appendedPhrase = appendedPhrase;
808
	}
809
810 8eebe79d m.geoffroy
	/** 
811 09887ea6 m.geoffroy
	 * Returns the details string of the {@link #getNomenclaturalReference() nomenclatural reference} assigned
812 b9d0e8d2 m.geoffroy
	 * to <i>this</i> taxon name. The details describe the exact localisation within
813 8eebe79d m.geoffroy
	 * the publication used as nomenclature reference. These are mostly
814
	 * (implicitly) pages but can also be figures or tables or any other
815
	 * element of a publication. A nomenclatural micro reference (details)
816
	 * requires the existence of a nomenclatural reference.
817
	 */
818
	//Details of the nomenclatural reference (protologue). 
819 9479da48 Andreas Müller
	public String getNomenclaturalMicroReference(){
820
		return this.nomenclaturalMicroReference;
821
	}
822 8eebe79d m.geoffroy
	/**
823
	 * @see  #getNomenclaturalMicroReference()
824
	 */
825 9479da48 Andreas Müller
	public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
826
		this.nomenclaturalMicroReference = nomenclaturalMicroReference;
827
	}
828
829 6680df00 Andreas Müller
	/* (non-Javadoc)
830
	 * @see eu.etaxonomy.cdm.model.common.IParsable#getHasProblem()
831 8eebe79d m.geoffroy
	 */
832 5b8e4457 Andreas Müller
	public int getParsingProblem(){
833
		return this.parsingProblem;
834 9479da48 Andreas Müller
	}
835 6680df00 Andreas Müller
	
836
	/* (non-Javadoc)
837 5ea47892 Andreas Müller
	 * @see eu.etaxonomy.cdm.model.common.IParsable#setHasProblem(int)
838 8eebe79d m.geoffroy
	 */
839 5b8e4457 Andreas Müller
	public void setParsingProblem(int parsingProblem){
840
		this.parsingProblem = parsingProblem;
841
	}
842
	
843
	/* (non-Javadoc)
844
	 * @see eu.etaxonomy.cdm.model.common.IParsable#addProblem(eu.etaxonomy.cdm.strategy.parser.NameParserWarning)
845
	 */
846 b314f1a8 Andreas Müller
	public void addParsingProblem(ParserProblem problem){
847
		parsingProblem = ParserProblem.addProblem(parsingProblem, problem);
848
	}
849
	
850
	/* (non-Javadoc)
851
	 * @see eu.etaxonomy.cdm.model.common.IParsable#removeParsingProblem(eu.etaxonomy.cdm.strategy.parser.ParserProblem)
852
	 */
853
	public void removeParsingProblem(ParserProblem problem) {
854
		parsingProblem = ParserProblem.removeProblem(parsingProblem, problem);
855 5b8e4457 Andreas Müller
	}
856
	
857
	/**
858
	 * @param warnings
859
	 */
860 b314f1a8 Andreas Müller
	public void addParsingProblems(int problems){
861
		parsingProblem = ParserProblem.addProblems(parsingProblem, problems);
862 9479da48 Andreas Müller
	}
863 6680df00 Andreas Müller
	
864
	/* (non-Javadoc)
865
	 * @see eu.etaxonomy.cdm.model.common.IParsable#hasProblem()
866 81c31b35 Andreas Müller
	 */
867 5b8e4457 Andreas Müller
	public boolean hasProblem(){
868
		return parsingProblem != 0;
869 81c31b35 Andreas Müller
	}
870 6680df00 Andreas Müller
	
871 b314f1a8 Andreas Müller
	
872
	
873
	/* (non-Javadoc)
874
	 * @see eu.etaxonomy.cdm.model.common.IParsable#hasProblem(eu.etaxonomy.cdm.strategy.parser.ParserProblem)
875
	 */
876
	public boolean hasProblem(ParserProblem problem) {
877
		return getParsingProblems().contains(problem);
878
	}
879
	
880
	
881 6680df00 Andreas Müller
	/* (non-Javadoc)
882
	 * @see eu.etaxonomy.cdm.model.common.IParsable#problemStarts()
883
	 */
884
	public int getProblemStarts(){
885
		return this.problemStarts;
886
	}
887
	
888
	/* (non-Javadoc)
889
	 * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemStarts(int)
890
	 */
891
	public void setProblemStarts(int start) {
892
		this.problemStarts = start;
893
	}
894
	
895
	/* (non-Javadoc)
896
	 * @see eu.etaxonomy.cdm.model.common.IParsable#problemEnds()
897
	 */
898
	public int getProblemEnds(){
899
		return this.problemEnds;
900
	}
901
902
	/* (non-Javadoc)
903
	 * @see eu.etaxonomy.cdm.model.common.IParsable#setProblemEnds(int)
904
	 */
905
	public void setProblemEnds(int end) {
906
		this.problemEnds = end;
907
	}
908
909 dce4c9cb Andreas Müller
//*********************** TYPE DESIGNATION *********************************************//	
910
	
911 79263e24 m.geoffroy
	/** 
912 dce4c9cb Andreas Müller
	 * Returns the set of {@link TypeDesignationBase type designations} assigned
913
	 * to <i>this</i> taxon name.
914 79263e24 m.geoffroy
	 * @see     NameTypeDesignation
915
	 * @see     SpecimenTypeDesignation
916
	 */
917 dce4c9cb Andreas Müller
	public Set<TypeDesignationBase> getTypeDesignations() {
918 a641fad9 ben.clark
		if(typeDesignations == null) {
919
			this.typeDesignations = new HashSet<TypeDesignationBase>();
920
		}
921 dce4c9cb Andreas Müller
		return typeDesignations;
922 9479da48 Andreas Müller
	}
923 dce4c9cb Andreas Müller
	
924
	/** 
925 6a9737e8 m.geoffroy
	 * Removes one element from the set of {@link TypeDesignationBase type designations} assigned to
926
	 * <i>this</i> taxon name. The type designation itself will be nullified.
927 dce4c9cb Andreas Müller
	 *
928
	 * @param  typeDesignation  the type designation which should be deleted
929
	 */
930
	public void removeTypeDesignation(TypeDesignationBase typeDesignation) {
931
		logger.warn("not yet fully implemented: nullify the specimen type designation itself?");
932
		this.typeDesignations.remove(typeDesignation);
933
	}
934
	
935
	/** 
936
	 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} assigned
937 6a9737e8 m.geoffroy
	 * to <i>this</i> taxon name. The {@link Rank rank} of <i>this</i> taxon name is generally
938
	 * "species" or below. The specimen type designations include all the
939
	 * specimens on which the typification of this name is based (which are
940 09887ea6 m.geoffroy
	 * exclusively used to typify taxon names belonging to the same
941 6a9737e8 m.geoffroy
	 * {@link HomotypicalGroup homotypical group} to which <i>this</i> taxon name
942
	 * belongs) and eventually the status of these designations.
943 dce4c9cb Andreas Müller
	 *
944
	 * @see     SpecimenTypeDesignation
945
	 * @see     NameTypeDesignation
946 6a9737e8 m.geoffroy
	 * @see     HomotypicalGroup
947 dce4c9cb Andreas Müller
	 */
948 b70a7f94 Andreas Kohlbecker
	@Transient
949 dce4c9cb Andreas Müller
	public Set<SpecimenTypeDesignation> getSpecimenTypeDesignationsOfHomotypicalGroup() {
950
		return this.getHomotypicalGroup().getSpecimenTypeDesignations();
951
	}
952
	
953
//*********************** NAME TYPE DESIGNATION *********************************************//	
954
	
955
	/** 
956
	 * Returns the set of {@link NameTypeDesignation name type designations} assigned
957
	 * to <i>this</i> taxon name the rank of which must be above "species".
958
	 * The name type designations include all the taxon names used to typify
959 d82717cb m.geoffroy
	 * <i>this</i> taxon name and eventually the rejected or conserved status
960 dce4c9cb Andreas Müller
	 * of these designations.
961
	 *
962
	 * @see     NameTypeDesignation
963
	 * @see     SpecimenTypeDesignation
964
	 */
965 b70a7f94 Andreas Kohlbecker
	@Transient
966 dce4c9cb Andreas Müller
	public Set<NameTypeDesignation> getNameTypeDesignations() {
967
		Set<NameTypeDesignation> result = new HashSet<NameTypeDesignation>();
968
		for (TypeDesignationBase typeDesignation : this.typeDesignations){
969
			if (typeDesignation instanceof NameTypeDesignation){
970
				result.add((NameTypeDesignation)typeDesignation);
971 c79406dd n.hoffmann
			}
972
		}
973 dce4c9cb Andreas Müller
		return result;
974 c79406dd n.hoffmann
	}
975 ed85df08 Andreas Müller
	
976
	/** 
977
	 * Creates and adds a new {@link NameTypeDesignation name type designation}
978 09887ea6 m.geoffroy
	 * to <i>this</i> taxon name's set of type designations.
979 ed85df08 Andreas Müller
	 *
980 b9d0e8d2 m.geoffroy
	 * @param  typeSpecies				the taxon name to be used as type of <i>this</i> taxon name
981 ed85df08 Andreas Müller
	 * @param  citation					the reference for this new designation
982
	 * @param  citationMicroReference	the string with the details (generally pages) within the reference
983 7d954fd9 m.geoffroy
	 * @param  originalNameString		the taxon name string used in the reference to assert this designation
984 6a9737e8 m.geoffroy
	 * @param  isRejectedType			the boolean status for a rejected name type designation
985
	 * @param  isConservedType			the boolean status for a conserved name type designation
986
	 * @param  isLectoType				the boolean status for a lectotype name type designation
987 d82717cb m.geoffroy
	 * @param  isNotDesignated			the boolean status for a name type designation without name type
988
	 * @param  addToAllHomotypicNames	the boolean indicating whether the name type designation should be
989
	 * 									added to all taxon names of the homotypical group this taxon name belongs to
990 ed85df08 Andreas Müller
	 * @see 			  				#getNameTypeDesignations()
991 6a9737e8 m.geoffroy
	 * @see 			  				NameTypeDesignation
992 57883822 m.geoffroy
	 * @see 			  				TypeDesignationBase#isNotDesignated()
993 ed85df08 Andreas Müller
	 */
994 dce4c9cb Andreas Müller
	public void addNameTypeDesignation(TaxonNameBase typeSpecies, 
995
				ReferenceBase citation, 
996
				String citationMicroReference, 
997
				String originalNameString, 
998 999f1f6b Andreas Müller
				NameTypeDesignationStatus status,
999 dce4c9cb Andreas Müller
				boolean isRejectedType, 
1000
				boolean isConservedType, 
1001 999f1f6b Andreas Müller
				/*boolean isLectoType, */
1002 dce4c9cb Andreas Müller
				boolean isNotDesignated, 
1003
				boolean addToAllHomotypicNames) {
1004 999f1f6b Andreas Müller
		NameTypeDesignation nameTypeDesignation = new NameTypeDesignation(typeSpecies, citation, citationMicroReference, originalNameString, status, isRejectedType, isConservedType, isNotDesignated);
1005
		//nameTypeDesignation.setLectoType(isLectoType);
1006 dce4c9cb Andreas Müller
		addTypeDesignation(nameTypeDesignation, addToAllHomotypicNames);
1007 ed85df08 Andreas Müller
	}
1008
	
1009 89fd9fcc a.babadshanjan
	/** 
1010
	 * Creates and adds a new {@link NameTypeDesignation name type designation}
1011
	 * to <i>this</i> taxon name's set of type designations.
1012
	 *
1013
	 * @param  typeSpecies				the taxon name to be used as type of <i>this</i> taxon name
1014
	 * @param  citation					the reference for this new designation
1015
	 * @param  citationMicroReference	the string with the details (generally pages) within the reference
1016
	 * @param  originalNameString		the taxon name string used in the reference to assert this designation
1017
	 * @param  status                   the name type designation status
1018
	 * @param  addToAllHomotypicNames	the boolean indicating whether the name type designation should be
1019
	 * 									added to all taxon names of the homotypical group this taxon name belongs to
1020
	 * @see 			  				#getNameTypeDesignations()
1021
	 * @see 			  				NameTypeDesignation
1022
	 * @see 			  				TypeDesignationBase#isNotDesignated()
1023
	 */
1024
	public void addNameTypeDesignation(TaxonNameBase typeSpecies, 
1025
				ReferenceBase citation, 
1026
				String citationMicroReference, 
1027
				String originalNameString,
1028
				NameTypeDesignationStatus status,
1029
				boolean addToAllHomotypicNames) {
1030
		NameTypeDesignation nameTypeDesignation = new NameTypeDesignation(typeSpecies, status, citation, citationMicroReference, originalNameString);
1031
		addTypeDesignation(nameTypeDesignation, addToAllHomotypicNames);
1032
	}
1033
	
1034 dce4c9cb Andreas Müller
//*********************** SPECIMEN TYPE DESIGNATION *********************************************//	
1035 ed85df08 Andreas Müller
	
1036 61106138 m.geoffroy
	/** 
1037
	 * Returns the set of {@link SpecimenTypeDesignation specimen type designations}
1038 b9d0e8d2 m.geoffroy
	 * that typify <i>this</i> taxon name.
1039 ed85df08 Andreas Müller
	 */
1040 b70a7f94 Andreas Kohlbecker
	@Transient
1041 dce4c9cb Andreas Müller
	public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
1042
		Set<SpecimenTypeDesignation> result = new HashSet<SpecimenTypeDesignation>();
1043
		for (TypeDesignationBase typeDesignation : this.typeDesignations){
1044
			if (typeDesignation instanceof SpecimenTypeDesignation){
1045
				result.add((SpecimenTypeDesignation)typeDesignation);
1046
			}
1047
		}
1048
		return result;
1049 66b77c3e m.geoffroy
	}
1050 dce4c9cb Andreas Müller
1051 66b77c3e m.geoffroy
	
1052 79263e24 m.geoffroy
	/** 
1053 d82717cb m.geoffroy
	 * Creates and adds a new {@link SpecimenTypeDesignation specimen type designation}
1054 09887ea6 m.geoffroy
	 * to <i>this</i> taxon name's set of type designations.
1055 79263e24 m.geoffroy
	 *
1056 d82717cb m.geoffroy
	 * @param  typeSpecimen				the specimen to be used as a type for <i>this</i> taxon name
1057 79263e24 m.geoffroy
	 * @param  status					the specimen type designation status
1058
	 * @param  citation					the reference for this new specimen type designation
1059
	 * @param  citationMicroReference	the string with the details (generally pages) within the reference
1060
	 * @param  originalNameString		the taxon name used in the reference to assert this designation
1061 57883822 m.geoffroy
	 * @param  isNotDesignated			the boolean status for a specimen type designation without specimen type
1062 d82717cb m.geoffroy
	 * @param  addToAllHomotypicNames	the boolean indicating whether the specimen type designation should be
1063
	 * 									added to all taxon names of the homotypical group the typified
1064
	 * 									taxon name belongs to
1065
	 * @see 			  				#getSpecimenTypeDesignations()
1066 2d4607f2 a.babadshanjan
	 * @see 			  				SpecimenTypeDesignationStatus
1067 d82717cb m.geoffroy
	 * @see 			  				SpecimenTypeDesignation
1068 57883822 m.geoffroy
	 * @see 			  				TypeDesignationBase#isNotDesignated()
1069 79263e24 m.geoffroy
	 */
1070 dce4c9cb Andreas Müller
	public void addSpecimenTypeDesignation(Specimen typeSpecimen, 
1071 2d4607f2 a.babadshanjan
				SpecimenTypeDesignationStatus status, 
1072 dce4c9cb Andreas Müller
				ReferenceBase citation, 
1073
				String citationMicroReference, 
1074
				String originalNameString, 
1075 57883822 m.geoffroy
				boolean isNotDesignated, 
1076 dce4c9cb Andreas Müller
				boolean addToAllHomotypicNames) {
1077 57883822 m.geoffroy
		SpecimenTypeDesignation specimenTypeDesignation = new SpecimenTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString, isNotDesignated);
1078 dce4c9cb Andreas Müller
		addTypeDesignation(specimenTypeDesignation, addToAllHomotypicNames);
1079 9479da48 Andreas Müller
	}
1080 ed85df08 Andreas Müller
	
1081 53befb32 Andreas Müller
	//used by merge strategy
1082
	private boolean addTypeDesignation(TypeDesignationBase typeDesignation){
1083
		return addTypeDesignation(typeDesignation, true);
1084
	}
1085
	
1086 dce4c9cb Andreas Müller
	private boolean addTypeDesignation(TypeDesignationBase typeDesignation, boolean addToAllNames){
1087
		//at them moment typeDesignations are not persisted with the homotypical group
1088
		//so explicit adding to the homotypical group is not necessary.
1089
		if (typeDesignation != null){
1090
			this.typeDesignations.add(typeDesignation);
1091
			typeDesignation.addTypifiedName(this);
1092
			
1093
			if (addToAllNames){
1094
				for (TaxonNameBase taxonName : this.getHomotypicalGroup().getTypifiedNames()){
1095
					if (taxonName != this){
1096
						taxonName.addTypeDesignation(typeDesignation, false);
1097
					}
1098
				}
1099
			}
1100
		}
1101
		return true;
1102 ed85df08 Andreas Müller
	}
1103 dce4c9cb Andreas Müller
	
1104 ed85df08 Andreas Müller
1105 dce4c9cb Andreas Müller
	
1106
//*********************** HOMOTYPICAL GROUP *********************************************//	
1107 9479da48 Andreas Müller
1108 dce4c9cb Andreas Müller
	
1109 79263e24 m.geoffroy
	/** 
1110
	 * Returns the {@link HomotypicalGroup homotypical group} to which
1111 b9d0e8d2 m.geoffroy
	 * <i>this</i> taxon name belongs. A homotypical group represents all taxon names
1112 d82717cb m.geoffroy
	 * that share the same types.
1113 79263e24 m.geoffroy
	 *
1114
	 * @see 	HomotypicalGroup
1115
	 */
1116 ee91bcd9 ben.clark
	
1117 9479da48 Andreas Müller
	public HomotypicalGroup getHomotypicalGroup() {
1118
		return homotypicalGroup;
1119
	}
1120 ee91bcd9 ben.clark
	
1121
	/* 
1122
	 * @see #getHomotypicalGroup()
1123
	 */
1124
	protected void setHomotypicalGroup(HomotypicalGroup homotypicalGroup) {
1125
		this.homotypicalGroup = homotypicalGroup;
1126 9479da48 Andreas Müller
	}
1127 30424f60 Andreas Müller
	
1128
	
1129 9479da48 Andreas Müller
1130 dce4c9cb Andreas Müller
// *************************************************************************//
1131
	
1132 b3262b1b m.geoffroy
	/** 
1133
	 * @see #getNomenclaturalReference()
1134
	 */
1135 b70a7f94 Andreas Kohlbecker
	@Transient
1136 57606ee3 Andreas Müller
	public ReferenceBase getCitation(){
1137 66b77c3e m.geoffroy
		//TODO What is the purpose of this method differing from the getNomenclaturalReference method? 
1138 c19dfdc5 Andreas Müller
		logger.warn("getCitation not yet implemented");
1139 9479da48 Andreas Müller
		return null;
1140
	}
1141
1142 66b77c3e m.geoffroy
	/** 
1143
	 * Returns the complete string containing the
1144 09887ea6 m.geoffroy
	 * {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
1145
	 * and the {@link #getNomenclaturalMicroReference() details} assigned to <i>this</i> taxon name.
1146 66b77c3e m.geoffroy
	 * 
1147 b9d0e8d2 m.geoffroy
	 * @return  the string containing the nomenclatural reference of <i>this</i> taxon name
1148 09887ea6 m.geoffroy
	 * @see		eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation()
1149 b3262b1b m.geoffroy
	 * @see		#getNomenclaturalReference()
1150
	 * @see		#getNomenclaturalMicroReference()
1151 66b77c3e m.geoffroy
	 */
1152 b70a7f94 Andreas Kohlbecker
	@Transient
1153 6680df00 Andreas Müller
	@Deprecated
1154 9479da48 Andreas Müller
	public String getCitationString(){
1155 c19dfdc5 Andreas Müller
		logger.warn("getCitationString not yet implemented");
1156 9479da48 Andreas Müller
		return null;
1157
	}
1158
1159 5b8e4457 Andreas Müller
	/**
1160
	 * Returns the parsing problems 
1161
	 * @return
1162 09887ea6 m.geoffroy
	 */
1163 5b8e4457 Andreas Müller
	public List<ParserProblem> getParsingProblems(){
1164
		return ParserProblem.warningList(this.parsingProblem);
1165 9479da48 Andreas Müller
	}
1166
1167
	/**
1168 66b77c3e m.geoffroy
	 * Returns the string containing the publication date (generally only year)
1169 09887ea6 m.geoffroy
	 * of the {@link #getNomenclaturalReference() nomenclatural reference} for <i>this</i> taxon name, null if there is
1170 b3262b1b m.geoffroy
	 * no nomenclatural reference.
1171 66b77c3e m.geoffroy
	 * 
1172 b9d0e8d2 m.geoffroy
	 * @return  the string containing the publication date of <i>this</i> taxon name
1173 09887ea6 m.geoffroy
	 * @see		eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getYear()
1174 9479da48 Andreas Müller
	 */
1175 b70a7f94 Andreas Kohlbecker
	@Transient
1176 b0b7280d Andreas Müller
	public String getReferenceYear(){
1177
		if (this.getNomenclaturalReference() != null ){
1178
			return this.getNomenclaturalReference().getYear();
1179
		}else{
1180
			return null;
1181
		}
1182 9479da48 Andreas Müller
	}
1183
1184 66b77c3e m.geoffroy
	/** 
1185 09887ea6 m.geoffroy
	 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
1186 66b77c3e m.geoffroy
	 * In this context a taxon base means the use of a taxon name by a reference
1187 09887ea6 m.geoffroy
	 * either as a {@link eu.etaxonomy.cdm.model.taxon.Taxon taxon} ("accepted/correct" name) or
1188
	 * as a (junior) {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
1189
	 * A taxon name can be used by several distinct {@link eu.etaxonomy.cdm.model.reference.ReferenceBase references} but only once
1190 66b77c3e m.geoffroy
	 * within a taxonomic treatment (identified by one reference).
1191
	 *
1192
	 * @see	#getTaxa()
1193
	 * @see	#getSynonyms()
1194
	 */
1195 608eada2 Andreas Müller
	public Set<TaxonBase> getTaxonBases() {
1196 a641fad9 ben.clark
		if(taxonBases == null) {
1197
			this.taxonBases = new HashSet<TaxonBase>();
1198
		}
1199 608eada2 Andreas Müller
		return this.taxonBases;
1200
	}
1201 ee91bcd9 ben.clark
	
1202 66b77c3e m.geoffroy
	/** 
1203 09887ea6 m.geoffroy
	 * Adds a new {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon base}
1204 b9d0e8d2 m.geoffroy
	 * to the set of taxon bases using <i>this</i> taxon name.
1205 66b77c3e m.geoffroy
	 *
1206
	 * @param  taxonBase  the taxon base to be added
1207
	 * @see 			  #getTaxonBases()
1208 61106138 m.geoffroy
	 * @see 			  #removeTaxonBase(TaxonBase)
1209 66b77c3e m.geoffroy
	 */
1210 1cfc54ab Andreas Müller
	//TODO protected
1211
	public void addTaxonBase(TaxonBase taxonBase){
1212 ee91bcd9 ben.clark
		Method method = ReflectionUtils.findMethod(TaxonBase.class, "setName", new Class[] {TaxonNameBase.class});
1213
		ReflectionUtils.makeAccessible(method);
1214
		ReflectionUtils.invokeMethod(method, taxonBase, new Object[] {this});
1215 1cfc54ab Andreas Müller
		taxonBases.add(taxonBase);
1216
	}
1217 b3262b1b m.geoffroy
	/** 
1218 09887ea6 m.geoffroy
	 * Removes one element from the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
1219 b3262b1b m.geoffroy
	 *
1220
	 * @param  taxonBase	the taxon base which should be removed from the corresponding set
1221 09887ea6 m.geoffroy
	 * @see    				#getTaxonBases()
1222 b3262b1b m.geoffroy
	 * @see    				#addTaxonBase(TaxonBase)
1223
	 */
1224 c1c3a21a Andreas Müller
	public void removeTaxonBase(TaxonBase taxonBase){
1225 ee91bcd9 ben.clark
		Method method = ReflectionUtils.findMethod(TaxonBase.class, "setName", new Class[] {TaxonNameBase.class});
1226
		ReflectionUtils.makeAccessible(method);
1227
		ReflectionUtils.invokeMethod(method, taxonBase, new Object[] {null});
1228 d163fbf6 Andreas Müller
		taxonBases.remove(taxonBase);
1229 1cfc54ab Andreas Müller
	}
1230
	
1231 0d4d2092 m.doering
	/**
1232 09887ea6 m.geoffroy
	 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Taxon taxa} ("accepted/correct" names according to any
1233 b9d0e8d2 m.geoffroy
	 * reference) that are based on <i>this</i> taxon name. This set is a subset of
1234 66b77c3e m.geoffroy
	 * the set returned by getTaxonBases(). 
1235
	 * 
1236 09887ea6 m.geoffroy
	 * @see	eu.etaxonomy.cdm.model.taxon.Taxon
1237 66b77c3e m.geoffroy
	 * @see	#getTaxonBases()
1238
	 * @see	#getSynonyms()
1239 0d4d2092 m.doering
	 */
1240 b70a7f94 Andreas Kohlbecker
	@Transient
1241 0d4d2092 m.doering
	public Set<Taxon> getTaxa(){
1242 608eada2 Andreas Müller
		Set<Taxon> result = new HashSet<Taxon>();
1243
		for (TaxonBase taxonBase : this.taxonBases){
1244
			if (taxonBase instanceof Taxon){
1245
				result.add((Taxon)taxonBase);
1246
			}
1247
		}
1248
		return result;
1249 0d4d2092 m.doering
	}
1250 608eada2 Andreas Müller
	
1251 0d4d2092 m.doering
	/**
1252 09887ea6 m.geoffroy
	 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Synonym (junior) synonyms} (according to any
1253 b9d0e8d2 m.geoffroy
	 * reference) that are based on <i>this</i> taxon name. This set is a subset of
1254 66b77c3e m.geoffroy
	 * the set returned by getTaxonBases(). 
1255
	 * 
1256 09887ea6 m.geoffroy
	 * @see	eu.etaxonomy.cdm.model.taxon.Synonym
1257 66b77c3e m.geoffroy
	 * @see	#getTaxonBases()
1258
	 * @see	#getTaxa()
1259 0d4d2092 m.doering
	 */
1260 b70a7f94 Andreas Kohlbecker
	@Transient
1261 608eada2 Andreas Müller
	public Set<Synonym> getSynonyms() {
1262
		Set<Synonym> result = new HashSet<Synonym>();
1263
		for (TaxonBase taxonBase : this.taxonBases){
1264
			if (taxonBase instanceof Synonym){
1265
				result.add((Synonym)taxonBase);
1266
			}
1267
		}
1268
		return result;
1269 0d4d2092 m.doering
	}
1270 9118658f m.doering
	
1271 71dcc146 Andreas Müller
	
1272
// *********** DESCRIPTIONS *************************************	
1273
1274 0880a77c m.geoffroy
	/**
1275 09887ea6 m.geoffroy
	 * Returns the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
1276 b9d0e8d2 m.geoffroy
	 * to <i>this</i> taxon name. A taxon name description is a piece of information
1277 0880a77c m.geoffroy
	 * concerning the taxon name like for instance the content of its first
1278
	 * publication (protolog) or a picture of this publication.
1279
	 * 
1280
	 * @see	#addDescription(TaxonNameDescription)
1281
	 * @see	#removeDescription(TaxonNameDescription)
1282 09887ea6 m.geoffroy
	 * @see	eu.etaxonomy.cdm.model.description.TaxonNameDescription
1283 0880a77c m.geoffroy
	 */
1284 71dcc146 Andreas Müller
	public Set<TaxonNameDescription> getDescriptions() {
1285
		return descriptions;
1286
	}
1287 ee91bcd9 ben.clark
1288 0880a77c m.geoffroy
	/** 
1289 09887ea6 m.geoffroy
	 * Adds a new {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name description}
1290 b9d0e8d2 m.geoffroy
	 * to the set of taxon name descriptions assigned to <i>this</i> taxon name. The
1291 09887ea6 m.geoffroy
	 * content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute} of the
1292 b9d0e8d2 m.geoffroy
	 * taxon name description itself will be replaced with <i>this</i> taxon name.
1293 0880a77c m.geoffroy
	 *
1294
	 * @param  description  the taxon name description to be added
1295
	 * @see					#getDescriptions()
1296
	 * @see 			  	#removeDescription(TaxonNameDescription)
1297 71dcc146 Andreas Müller
	 */
1298
	public void addDescription(TaxonNameDescription description) {
1299 fd7ee7b1 ben.clark
		java.lang.reflect.Field field = ReflectionUtils.findField(TaxonNameDescription.class, "taxonName", TaxonNameBase.class);
1300 c49c125c Andreas Müller
		ReflectionUtils.makeAccessible(field);
1301
		ReflectionUtils.setField(field, description, this);
1302 71dcc146 Andreas Müller
		descriptions.add(description);
1303
	}
1304 0880a77c m.geoffroy
	/** 
1305 09887ea6 m.geoffroy
	 * Removes one element from the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
1306
	 * to <i>this</i> taxon name. The content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute}
1307 0880a77c m.geoffroy
	 * of the description itself will be set to "null".
1308
	 *
1309
	 * @param  description  the taxon name description which should be removed
1310
	 * @see     		  	#getDescriptions()
1311
	 * @see     		  	#addDescription(TaxonNameDescription)
1312 09887ea6 m.geoffroy
	 * @see 			  	eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName()
1313 0880a77c m.geoffroy
	 */
1314 71dcc146 Andreas Müller
	public void removeDescription(TaxonNameDescription description) {
1315 fd7ee7b1 ben.clark
		java.lang.reflect.Field field = ReflectionUtils.findField(TaxonNameDescription.class, "taxonName", TaxonNameBase.class);
1316 c49c125c Andreas Müller
		ReflectionUtils.makeAccessible(field);
1317
		ReflectionUtils.setField(field, description, null);
1318 71dcc146 Andreas Müller
		descriptions.remove(description);
1319
	}
1320
	
1321 30424f60 Andreas Müller
// *********** HOMOTYPIC GROUP METHODS **************************************************
1322
1323
	@Transient
1324
	public void mergeHomotypicGroups(TaxonNameBase name){
1325
		this.getHomotypicalGroup().merge(name.getHomotypicalGroup());
1326
		//HomotypicalGroup thatGroup = name.homotypicalGroup;
1327
		name.setHomotypicalGroup(this.homotypicalGroup);
1328
	}
1329
	
1330 66b77c3e m.geoffroy
	/**
1331
	 * Returns the boolean value indicating whether a given taxon name belongs
1332 b9d0e8d2 m.geoffroy
	 * to the same {@link HomotypicalGroup homotypical group} as <i>this</i> taxon name (true)
1333 66b77c3e m.geoffroy
	 * or not (false). Returns "true" only if the homotypical groups of both
1334
	 * taxon names exist and if they are identical. 
1335
	 *
1336
	 * @param	homoTypicName  the taxon name the homotypical group of which is to be checked
1337
	 * @return  			   the boolean value of the check
1338
	 * @see     			   HomotypicalGroup
1339
	 */
1340 b70a7f94 Andreas Kohlbecker
	@Transient
1341 95449e99 Andreas Müller
	public boolean isHomotypic(TaxonNameBase homoTypicName) {
1342
		if (homoTypicName == null) {
1343
			return false;
1344
		}
1345
		HomotypicalGroup homotypicGroup = homoTypicName.getHomotypicalGroup();
1346
		if (homotypicGroup == null || this.getHomotypicalGroup() == null) {
1347
			return false;
1348
		}
1349
		if (homotypicGroup.equals(this.getHomotypicalGroup())) {
1350
			return true;
1351
		}
1352
		return false;
1353
	}
1354
	
1355 30424f60 Andreas Müller
	
1356
    /**
1357
     * Checks whether name is a basionym for ALL names
1358
     * in its homotypical group.
1359
     * Returns <code>false</code> if there are no other names in the group
1360
     * @param name
1361
     * @return
1362
     */  
1363
	@Transient
1364
	public boolean isGroupsBasionym() {
1365
		Set<TaxonNameBase> typifiedNames = homotypicalGroup.getTypifiedNames();
1366
		
1367
		// Check whether there are any other names in the group
1368
	    if (typifiedNames.size() == 1) {
1369
	            return false;
1370
	    }
1371
	   
1372
	    boolean isBasionymToAll = true;
1373
	                   
1374
	    for (TaxonNameBase taxonName : typifiedNames) {
1375
	            if (!taxonName.equals(this)) {
1376
	                    if (! isBasionymFor(taxonName)) {
1377
	                            return false;
1378
	                    }
1379
	            }
1380
	    }
1381
	    return true;            
1382
	}
1383
	
1384
    /**
1385
     * Checks whether a basionym relationship exists between fromName and toName.
1386
     *
1387
     * @param fromName
1388
     * @param toName
1389
     * @return
1390
     */
1391
	@Transient
1392
	public boolean isBasionymFor(TaxonNameBase newCombinationName) {
1393
            Set<NameRelationship> relations = newCombinationName.getRelationsToThisName();
1394
            for (NameRelationship relation : relations) {
1395
                    if (relation.getType().equals(NameRelationshipType.BASIONYM()) &&
1396
                                    relation.getFromName().equals(this)) {
1397
                            return true;
1398
                    }
1399
            }
1400
            return false;
1401
    }
1402
    
1403
    /**
1404
     * Creates a basionym relationship to all other names in this names homotypical
1405
     * group.
1406
     * 
1407
     * @see HomotypicalGroup.setGroupBasionym(TaxonNameBase basionymName)
1408
1409
     */
1410
	/* (non-Javadoc)
1411
	 * @see eu.etaxonomy.cdm.model.name.HomotypicalGroup#setGroupBasionym(TaxonNameBase)
1412
	 */
1413
	@Transient
1414
	public void makeGroupsBasionym() {
1415
        this.homotypicalGroup.setGroupBasionym(this);
1416
    }
1417
	
1418
	
1419 95449e99 Andreas Müller
//*********  Rank comparison shortcuts   ********************//
1420 4cc4f6f7 m.geoffroy
	/**
1421 b9d0e8d2 m.geoffroy
	 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1422 4cc4f6f7 m.geoffroy
	 * taxon name is higher than the genus rank (true) or not (false).
1423
	 * Suprageneric non viral names are monomials.
1424 bef42c31 Andreas Müller
	 * Returns false if rank is null.
1425 4cc4f6f7 m.geoffroy
	 * 
1426
	 * @see  #isGenus()
1427
	 * @see  #isInfraGeneric()
1428
	 * @see  #isSpecies()
1429
	 * @see  #isInfraSpecific()
1430
	 */
1431 b70a7f94 Andreas Kohlbecker
	@Transient
1432 451c6005 m.doering
	public boolean isSupraGeneric() {
1433 bef42c31 Andreas Müller
		if (rank == null){
1434
			return false;
1435
		}
1436 451c6005 m.doering
		return getRank().isSupraGeneric();
1437
	}
1438 4cc4f6f7 m.geoffroy
	/**
1439 b9d0e8d2 m.geoffroy
	 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1440 4cc4f6f7 m.geoffroy
	 * taxon name is the genus rank (true) or not (false). Non viral names with
1441 10a54497 m.geoffroy
	 * genus rank are monomials. Returns false if rank is null.
1442 4cc4f6f7 m.geoffroy
	 *
1443
	 * @see  #isSupraGeneric()
1444
	 * @see  #isInfraGeneric()
1445
	 * @see  #isSpecies()
1446
	 * @see  #isInfraSpecific()
1447
	 */
1448 b70a7f94 Andreas Kohlbecker
	@Transient
1449 451c6005 m.doering
	public boolean isGenus() {
1450 bef42c31 Andreas Müller
		if (rank == null){
1451
			return false;
1452
		}
1453 451c6005 m.doering
		return getRank().isGenus();
1454
	}
1455 4cc4f6f7 m.geoffroy
	/**
1456 b9d0e8d2 m.geoffroy
	 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1457 10a54497 m.geoffroy
	 * taxon name is higher than the species rank and lower than the
1458
	 * genus rank (true) or not (false). Infrageneric non viral names are
1459
	 * binomials. Returns false if rank is null.
1460 4cc4f6f7 m.geoffroy
	 *
1461
	 * @see  #isSupraGeneric()
1462
	 * @see  #isGenus()
1463
	 * @see  #isSpecies()
1464
	 * @see  #isInfraSpecific()
1465
	 */
1466 b70a7f94 Andreas Kohlbecker
	@Transient
1467 451c6005 m.doering
	public boolean isInfraGeneric() {
1468 bef42c31 Andreas Müller
		if (rank == null){
1469
			return false;
1470
		}
1471 451c6005 m.doering
		return getRank().isInfraGeneric();
1472
	}
1473 4cc4f6f7 m.geoffroy
	/**
1474 b9d0e8d2 m.geoffroy
	 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1475 10a54497 m.geoffroy
	 * taxon name is the species rank (true) or not (false). Non viral names
1476 4cc4f6f7 m.geoffroy
	 * with species rank are binomials.
1477 bef42c31 Andreas Müller
	 * Returns false if rank is null.
1478 4cc4f6f7 m.geoffroy
	 *
1479
	 * @see  #isSupraGeneric()
1480
	 * @see  #isGenus()
1481
	 * @see  #isInfraGeneric()
1482
	 * @see  #isInfraSpecific()
1483
	 */
1484 b70a7f94 Andreas Kohlbecker
	@Transient
1485 451c6005 m.doering
	public boolean isSpecies() {
1486 bef42c31 Andreas Müller
		if (rank == null){
1487
			return false;
1488
		}
1489 451c6005 m.doering
		return getRank().isSpecies();
1490
	}
1491 4cc4f6f7 m.geoffroy
	/**
1492 b9d0e8d2 m.geoffroy
	 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1493 4cc4f6f7 m.geoffroy
	 * taxon name is lower than the species rank (true) or not (false).
1494
	 * Infraspecific non viral names are trinomials.
1495 bef42c31 Andreas Müller
	 * Returns false if rank is null.
1496 4cc4f6f7 m.geoffroy
	 *
1497
	 * @see  #isSupraGeneric()
1498
	 * @see  #isGenus()
1499
	 * @see  #isInfraGeneric()
1500
	 * @see  #isSpecies()
1501
	 */
1502 b70a7f94 Andreas Kohlbecker
	@Transient
1503 451c6005 m.doering
	public boolean isInfraSpecific() {
1504 bef42c31 Andreas Müller
		if (rank == null){
1505
			return false;
1506
		}
1507 451c6005 m.doering
		return getRank().isInfraSpecific();
1508
	}
1509 5c19d7f0 Andreas Müller
	
1510 7ebeb288 Andreas Müller
	
1511 4cc4f6f7 m.geoffroy
	/**
1512 eb7e638a m.geoffroy
	 * Returns null as the {@link NomenclaturalCode nomenclatural code} that governs
1513 b9d0e8d2 m.geoffroy
	 * the construction of <i>this</i> taxon name since there is no specific
1514 eb7e638a m.geoffroy
	 * nomenclatural code defined. The real implementention takes place in the
1515
	 * subclasses {@link ViralName ViralName}, {@link BacterialName BacterialName},
1516
	 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName} and
1517
	 * {@link ZoologicalName ZoologicalName}. Each taxon name is governed by one
1518 4cc4f6f7 m.geoffroy
	 * and only one nomenclatural code. 
1519
	 *
1520 eb7e638a m.geoffroy
	 * @return  null
1521 b3262b1b m.geoffroy
	 * @see  	#isCodeCompliant()
1522
	 * @see  	#getHasProblem()
1523 4cc4f6f7 m.geoffroy
	 */
1524 bef42c31 Andreas Müller
	abstract public NomenclaturalCode getNomenclaturalCode();
1525 d50a2c5d Andreas Müller
	/* (non-Javadoc)
1526
	 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1527
	 */
1528 b3262b1b m.geoffroy
	/**
1529 b9d0e8d2 m.geoffroy
	 * Generates and returns the string with the scientific name of <i>this</i>
1530 7e759003 m.geoffroy
	 * taxon name (only non viral taxon names can be generated from their
1531
	 * components). This string may be stored in the inherited
1532 09887ea6 m.geoffroy
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
1533 b3262b1b m.geoffroy
	 * This method overrides the generic and inherited
1534 09887ea6 m.geoffroy
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() method} from
1535
	 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
1536 b3262b1b m.geoffroy
	 *
1537
	 * @return  the string with the composed name of this non viral taxon name with authorship (and maybe year)
1538 09887ea6 m.geoffroy
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1539
	 * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
1540 b3262b1b m.geoffroy
	 */
1541 4208745a ben.clark
//	@Override
1542
//	public abstract String generateTitle();
1543 dadf5cd0 Andreas Kohlbecker
}