Project

General

Profile

Download (35.2 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.name;
11

    
12
import java.util.HashMap;
13
import java.util.List;
14
import java.util.Map;
15
import java.util.UUID;
16

    
17
import javax.persistence.Entity;
18
import javax.persistence.Transient;
19
import javax.xml.bind.annotation.XmlAccessType;
20
import javax.xml.bind.annotation.XmlAccessorType;
21
import javax.xml.bind.annotation.XmlType;
22

    
23
import org.apache.log4j.Logger;
24
import org.hibernate.envers.Audited;
25
import org.hibernate.search.annotations.Indexed;
26

    
27
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
28
import eu.etaxonomy.cdm.model.common.Language;
29
import eu.etaxonomy.cdm.model.common.OrderedTermBase;
30
import eu.etaxonomy.cdm.model.common.Representation;
31
import eu.etaxonomy.cdm.model.common.TermVocabulary;
32
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
33

    
34
/**
35
 * The class representing the taxonomical ranks (like "Family", "Genus" or
36
 * "Species") used for {@link TaxonNameBase taxon names} across all {@link NomenclaturalCode nomenclatural codes}
37
 * for bacteria (ICNB), viruses (ICVCN), plants and fungi (ICBN),
38
 * cultivars (ICNCP) and animals (ICZN).
39
 * <P>
40
 * A standard (ordered) list of taxonomical rank instances will be automatically
41
 * created as the project starts. But this class allows to extend this standard
42
 * list by creating new instances of additional taxonomical ranks if needed. 
43
 * <P>
44
 * This class corresponds to: <ul>
45
 * <li> TaxonRankTerm according to the TDWG ontology
46
 * <li> TaxonomicRankEnum according to the TCS
47
 * <li> Rank according to the ABCD schema
48
 * </ul>
49
 * 
50
 * @author m.doering
51
 * @version 1.0
52
 * @created 08-Nov-2007 13:06:46
53
 */
54
@XmlAccessorType(XmlAccessType.FIELD)
55
@XmlType(name = "Rank")
56
@Entity
57
@Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
58
@Audited
59
public class Rank extends OrderedTermBase<Rank> {
60
	private static final long serialVersionUID = -8648081681348758485L;
61
	private static final Logger logger = Logger.getLogger(Rank.class);
62
	
63
	private static final UUID uuidEmpire = UUID.fromString("ac470211-1586-4b24-95ca-1038050b618d");
64
	private static final UUID uuidDomain = UUID.fromString("ffca6ec8-8b88-417b-a6a0-f7c992aac19b");
65
	private static final UUID uuidSuperkingdom = UUID.fromString("64223610-7625-4cfd-83ad-b797bf7f0edd");
66
	private static final UUID uuidKingdom = UUID.fromString("fbe7109d-66b3-498c-a697-c6c49c686162");
67
	private static final UUID uuidSubkingdom = UUID.fromString("a71bd9d8-f3ab-4083-afb5-d89315d71655");
68
	private static final UUID uuidInfrakingdom = UUID.fromString("1e37930c-86cf-44f6-90fd-7822928df260");
69
	private static final UUID uuidSuperphylum = UUID.fromString("0d0cecb1-e254-4607-b210-6801e7ecbb04");
70
	private static final UUID uuidPhylum = UUID.fromString("773430d2-76b4-438c-b817-97a543a33287");
71
	private static final UUID uuidSubphylum = UUID.fromString("23a9b6ff-9408-49c9-bd9e-7a2ca5ab4725");
72
	private static final UUID uuidInfraphylum = UUID.fromString("1701de3a-7693-42a5-a2d3-42697f944190");
73
	private static final UUID uuidSuperdivision = UUID.fromString("a735a48f-4fc8-49a7-ae0c-6a984f658131");
74
	private static final UUID uuidDivision = UUID.fromString("7e56f5cc-123a-4fd1-8cbb-6fd80358b581");
75
	private static final UUID uuidSubdivision = UUID.fromString("931c840f-7a6b-4d76-ad38-bfdd77d7b2e8");
76
	private static final UUID uuidInfradivision = UUID.fromString("c0ede273-be52-4dee-b411-66ee08d30c94");
77
	private static final UUID uuidSuperclass = UUID.fromString("e65b4e1a-21ec-428d-9b9f-e87721ab967c");
78
	private static final UUID uuidClass = UUID.fromString("f23d14c4-1d34-4ee6-8b4e-eee2eb9a3daf");
79
	private static final UUID uuidSubclass = UUID.fromString("8cb26733-e2f5-46cb-ab5c-f99254f877aa");
80
	private static final UUID uuidInfraclass = UUID.fromString("ad23cfda-879a-4021-8629-c54d27caf717");
81
	private static final UUID uuidSuperorder = UUID.fromString("c8c67a22-301a-4219-b882-4a49121232ff");
82
	private static final UUID uuidOrder = UUID.fromString("b0785a65-c1c1-4eb4-88c7-dbd3df5aaad1");
83
	private static final UUID uuidSuborder = UUID.fromString("768ad378-fa85-42ab-b668-763225832f57");
84
	private static final UUID uuidInfraorder = UUID.fromString("84099182-a6f5-47d7-8586-33c9e9955a10");
85
	private static final UUID uuidSectionZoology = UUID.fromString("691d371e-10d7-43f0-93db-3d7fa1a62c54");
86
	private static final UUID uuidSubsectionZoology = UUID.fromString("0ed32d28-adc4-4303-a9ca-68e2acd67e33");
87
	private static final UUID uuidSuperfamily = UUID.fromString("2cfa510a-dcea-4a03-b66a-b1528f9b0796");
88
	private static final UUID uuidFamily = UUID.fromString("af5f2481-3192-403f-ae65-7c957a0f02b6");
89
	private static final UUID uuidSubfamily = UUID.fromString("862526ee-7592-4760-a23a-4ff3641541c5");
90
	private static final UUID uuidInfrafamily = UUID.fromString("c3f2e3bb-6eef-4a26-9fb7-b14f4c8c5e4f");
91
	private static final UUID uuidSupertribe = UUID.fromString("11e94828-8c61-499b-87d6-1de35ce2c51c");
92
	private static final UUID uuidTribe = UUID.fromString("4aa6890b-0363-4899-8d7c-ee0cb78e6166");
93
	private static final UUID uuidSubtribe = UUID.fromString("ae41ecc5-5165-4126-9d24-79939ae5d822");
94
	private static final UUID uuidInfratribe = UUID.fromString("1ec02e8f-f2b7-4c65-af9f-b436b34c79a3");
95
	private static final UUID uuidSupragenericTaxon = UUID.fromString("1fdc0b93-c354-441a-8406-091e0303ff5c");
96
	private static final UUID uuidGenus = UUID.fromString("1b11c34c-48a8-4efa-98d5-84f7f66ef43a");
97
	private static final UUID uuidSubgenus = UUID.fromString("78786e16-2a70-48af-a608-494023b91904");
98
	private static final UUID uuidInfragenus = UUID.fromString("a9972969-82cd-4d54-b693-a096422f13fa");
99
	private static final UUID uuidSectionBotany = UUID.fromString("3edff68f-8527-49b5-bf91-7e4398bb975c");
100
	private static final UUID uuidSubsectionBotany = UUID.fromString("d20f5b61-d463-4448-8f8a-c1ff1f262f59");
101
	private static final UUID uuidSeries = UUID.fromString("d7381ecf-48f8-429b-9c54-f461656978cd");
102
	private static final UUID uuidSubseries = UUID.fromString("80c9a263-f4db-4a13-b6c2-b7fec1aa1200");
103
	private static final UUID uuidSpeciesAggregate = UUID.fromString("1ecae058-4217-4f75-9c27-6d8ba099ac7a");
104
	private static final UUID uuidSpeciesGroup = UUID.fromString("d1988a11-292b-46fa-8fb7-bc64ea6d8fc6");
105
	private static final UUID uuidInfragenericTaxon = UUID.fromString("41bcc6ac-37d3-4fd4-bb80-3cc5b04298b9");
106
	public static final UUID uuidSpecies = UUID.fromString("b301f787-f319-4ccc-a10f-b4ed3b99a86d");
107
	private static final UUID uuidSubspecificAggregate = UUID.fromString("72c248b9-027d-4402-b375-dd4f0850c9ad");
108
	private static final UUID uuidSubspecies = UUID.fromString("462a7819-8b00-4190-8313-88b5be81fad5");
109
	private static final UUID uuidInfraspecies = UUID.fromString("f28ebc9e-bd50-4194-9af1-42f5cb971a2c");
110
	private static final UUID uuidNatio = UUID.fromString("965f2f38-7f97-4270-ab5a-1999bf050a22");
111
	private static final UUID uuidVariety = UUID.fromString("d5feb6a5-af5c-45ef-9878-bb4f36aaf490");
112
	private static final UUID uuidBioVariety = UUID.fromString("a3a364cb-1a92-43fc-a717-3c44980a0991");
113
	private static final UUID uuidPathoVariety = UUID.fromString("2f4f4303-a099-47e3-9048-d749d735423b");
114
	private static final UUID uuidSubvariety = UUID.fromString("9a83862a-7aee-480c-a98d-4bceaf8712ca");
115
	private static final UUID uuidSubsubvariety = UUID.fromString("bff22f84-553a-4429-a4e7-c4b3796c3a18");
116
	private static final UUID uuidConvar = UUID.fromString("2cc740c9-cebb-43c8-9b06-1bef79e6a56a");
117
	private static final UUID uuidForm = UUID.fromString("0461281e-458a-47b9-8d41-19a3d39356d5");
118
	private static final UUID uuidSpecialForm = UUID.fromString("bed20aee-2f5a-4635-9c02-eff06246d067");
119
	private static final UUID uuidSubform = UUID.fromString("47cfc5b0-0fb7-4ceb-b61d-e1dd8de8b569");
120
	private static final UUID uuidSubsubform = UUID.fromString("1c8ac389-4349-4ae0-87be-7239f6635068");
121
	private static final UUID uuidInfraspecificTaxon = UUID.fromString("eb75c27d-e154-4570-9d96-227b2df60474");
122
	private static final UUID uuidCandidate = UUID.fromString("ead9a1f5-dfd4-4de2-9121-70a47accb10b");
123
	private static final UUID uuidDenominationClass = UUID.fromString("49bdf74a-2170-40ed-8be2-887a0db517bf");
124
	private static final UUID uuidGrex = UUID.fromString("08dcb4ff-ac58-48a3-93af-efb3d836ac84");
125
	private static final UUID uuidGraftChimaera = UUID.fromString("6b4063bc-f934-4796-9bf3-0ef3aea5c1cb");
126
	private static final UUID uuidCultivarGroup = UUID.fromString("d763e7d3-e7de-4bb1-9d75-225ca6948659");
127
	private static final UUID uuidCultivar = UUID.fromString("5e98415b-dc6e-440b-95d6-ea33dbb39ad0");
128
	private static final UUID uuidUnknownRank = UUID.fromString("5c4d6755-2cf6-44ca-9220-cccf8881700b");
129
//	private static final UUID uuidUnrankedInfraSpecific = UUID.fromString("a965befb-70a9-4747-a18f-624456c65223");
130
//	private static final UUID uuidUnrankedInfraGeneric = UUID.fromString("994646a1-c2e7-461d-a1bc-2afd6ea51b40");
131
	
132
	private static Map<String, UUID> abbrevMap = null;
133
	private static Map<String, UUID> labelMap = null;
134

    
135
	protected static Map<UUID, Rank> termMap = null;		
136

    
137
	
138
// ********************* CONSTRUCTORS ************************************+/	
139
	/** 
140
	 * Class constructor: creates a new empty rank instance.
141
	 * 
142
	 * @see 	#Rank(String, String, String)
143
	 */
144
	public Rank() {
145
	}
146

    
147
	/** 
148
	 * Class constructor: creates an additional rank instance with a description
149
	 * (in the {@link eu.etaxonomy.cdm.model.common.Language#DEFAULT() default language}), a label and a label abbreviation.
150
	 * 
151
	 * @param	term  		 the string (in the default language) describing the
152
	 * 						 new rank to be created 
153
	 * @param	label  		 the string identifying the new rank to be created
154
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
155
	 * 						 new rank to be created
156
	 * @see 	#Rank()
157
	 */
158
	public Rank(String term, String label, String labelAbbrev) {
159
		super(term, label, labelAbbrev);
160
	}
161

    
162
	/** 
163
	 * Creates a new empty rank.
164
	 * 
165
	 * @see #NewInstance(String, String, String)
166
	 */
167
	private static Rank NewInstance(){
168
		return new Rank();
169
	}
170
	
171
	/** 
172
	 * Creates an additional rank with a description (in the {@link Language#DEFAULT() default language}),
173
	 * a label and a label abbreviation.
174
	 * 
175
	 * @param	term  		 the string (in the default language) describing the
176
	 * 						 new rank to be created 
177
	 * @param	label  		 the string identifying the new rank to be created
178
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
179
	 * 						 new rank to be created
180
	 * @see 				 #NewInstance()
181
	 */
182
	private static Rank NewInstance(String term, String label, String labelAbbrev){
183
		return new Rank(term, label, labelAbbrev);
184
	}
185

    
186
//********* METHODS **************************************/
187
	
188
	/* (non-Javadoc)
189
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#resetTerms()
190
	 */
191
	@Override
192
	public void resetTerms(){
193
		termMap = null;
194
	}
195

    
196
	
197
	
198
	protected static Rank getTermByUuid(UUID uuid){
199
		if (termMap == null){
200
			return null;  //better return null then initialize the termMap in an unwanted way 
201
		}
202
		return (Rank)termMap.get(uuid);
203
	}
204
	
205
	public static final Rank EMPIRE(){
206
	  return getTermByUuid(uuidEmpire);
207
	}
208
	public static final Rank DOMAIN(){
209
		  return getTermByUuid(uuidDomain);	
210
	}
211
	public static final Rank SUPERKINGDOM(){
212
		return getTermByUuid(uuidSuperkingdom);
213
	}
214
	public static final Rank KINGDOM(){
215
		return getTermByUuid(uuidKingdom);
216
	}
217
	public static final Rank SUBKINGDOM(){
218
		return getTermByUuid(uuidSubkingdom);
219
	}
220
	public static final Rank INFRAKINGDOM(){
221
		return getTermByUuid(uuidInfrakingdom);
222
	}
223
	public static final Rank SUPERPHYLUM(){
224
		return getTermByUuid(uuidSuperphylum);
225
	}
226
	public static final Rank PHYLUM(){
227
		return getTermByUuid(uuidPhylum);
228
	}
229
	public static final Rank SUBPHYLUM(){
230
		return getTermByUuid(uuidSubphylum);
231
	}
232
	public static final Rank INFRAPHYLUM(){
233
		return getTermByUuid(uuidInfraphylum);
234
	}
235
	public static final Rank SUPERDIVISION(){
236
		return getTermByUuid(uuidSuperdivision);
237
	}
238
	public static final Rank DIVISION(){
239
		return getTermByUuid(uuidDivision);
240
	}
241
	public static final Rank SUBDIVISION(){
242
		return getTermByUuid(uuidSubdivision);
243
	}
244
	public static final Rank INFRADIVISION(){
245
		return getTermByUuid(uuidInfradivision);
246
	}
247
	public static final Rank SUPERCLASS(){
248
		return getTermByUuid(uuidSuperclass);
249
	}
250
	public static final Rank CLASS(){
251
		return getTermByUuid(uuidClass);
252
	}
253
	public static final Rank SUBCLASS(){
254
		return getTermByUuid(uuidSubclass);
255
	}
256
	public static final Rank INFRACLASS(){
257
		return getTermByUuid(uuidInfraclass);
258
	}
259
	public static final Rank SUPERORDER(){
260
		return getTermByUuid(uuidSuperorder);
261
	}
262
	public static final Rank ORDER(){
263
		return getTermByUuid(uuidOrder);
264
	}
265
	public static final Rank SUBORDER(){
266
		return getTermByUuid(uuidSuborder);
267
	}
268
	public static final Rank INFRAORDER(){
269
		return getTermByUuid(uuidInfraorder);
270
	}
271
	public static final Rank SUPERFAMILY(){
272
		return getTermByUuid(uuidSuperfamily);
273
	}
274
	public static final Rank FAMILY(){
275
		return getTermByUuid(uuidFamily);
276
	}
277
	public static final Rank SUBFAMILY(){
278
		return getTermByUuid(uuidSubfamily);
279
	}
280
	public static final Rank INFRAFAMILY(){
281
		return getTermByUuid(uuidInfrafamily);
282
	}
283
	public static final Rank SUPERTRIBE(){
284
		return getTermByUuid(uuidSupertribe);
285
	}
286
	public static final Rank TRIBE(){
287
		return getTermByUuid(uuidTribe);
288
	}
289
	public static final Rank SUBTRIBE(){
290
		return getTermByUuid(uuidSubtribe);
291
	}
292
	public static final Rank INFRATRIBE(){
293
		return getTermByUuid(uuidInfratribe);
294
	}
295
	public static final Rank SUPRAGENERICTAXON(){
296
		return getTermByUuid(uuidSupragenericTaxon);
297
	}
298
	public static final Rank GENUS(){
299
		return getTermByUuid(uuidGenus);
300
	}
301
	public static final Rank SUBGENUS(){
302
		return getTermByUuid(uuidSubgenus);
303
	}
304
	public static final Rank INFRAGENUS(){
305
		return getTermByUuid(uuidInfragenus);
306
	}
307
	public static final Rank SECTION_BOTANY(){
308
		return getTermByUuid(uuidSectionBotany);
309
	}
310
	public static final Rank SUBSECTION_BOTANY(){
311
		return getTermByUuid(uuidSubsectionBotany);
312
	}
313
	public static final Rank SECTION_ZOOLOGY(){
314
		return getTermByUuid(uuidSectionZoology);
315
	}
316
	public static final Rank SUBSECTION_ZOOLOGY(){
317
		return getTermByUuid(uuidSubsectionZoology);
318
	}
319
	public static final Rank SERIES(){
320
		return getTermByUuid(uuidSeries);
321
	}
322
	public static final Rank SUBSERIES(){
323
		return getTermByUuid(uuidSubseries);
324
	}
325
	public static final Rank SPECIESAGGREGATE(){
326
		return getTermByUuid(uuidSpeciesAggregate);
327
	}
328
	public static final Rank SPECIESGROUP(){
329
		return getTermByUuid(uuidSpeciesGroup);
330
	}
331
	/**
332
	 * 'Unranked infrageneric'. An infrageneric rank which is on purpose not further defined.
333
	 * This sometimes holds for names from the 19th century. 
334
	 */
335

    
336
	public static final Rank INFRAGENERICTAXON(){
337
		return getTermByUuid(uuidInfragenericTaxon);
338
	}
339
	public static final Rank SPECIES(){
340
		return getTermByUuid(uuidSpecies);
341
	}
342
	public static final Rank SUBSPECIFICAGGREGATE(){
343
		return getTermByUuid(uuidSubspecificAggregate);
344
	}
345
	public static final Rank SUBSPECIES(){
346
		return getTermByUuid(uuidSubspecies);
347
	}
348
	public static final Rank INFRASPECIES(){
349
		return getTermByUuid(uuidInfraspecies);
350
	}
351
	public static final Rank VARIETY(){
352
		return getTermByUuid(uuidVariety);
353
	}
354
	public static final Rank BIOVARIETY(){
355
		return getTermByUuid(uuidBioVariety);
356
	}
357
	public static final Rank PATHOVARIETY(){
358
		return getTermByUuid(uuidPathoVariety);
359
	}
360
	public static final Rank SUBVARIETY(){
361
		return getTermByUuid(uuidSubvariety);
362
	}
363
	public static final Rank SUBSUBVARIETY(){
364
		return getTermByUuid(uuidSubsubvariety );
365
	}
366
	public static final Rank CONVAR(){
367
		return getTermByUuid(uuidConvar);
368
	}
369
	public static final Rank FORM(){
370
		return getTermByUuid(uuidForm);
371
	}
372
	public static final Rank SPECIALFORM(){
373
		return getTermByUuid(uuidSpecialForm);
374
	}
375
	public static final Rank SUBFORM(){
376
		return getTermByUuid(uuidSubform);
377
	}
378
	public static final Rank SUBSUBFORM(){
379
		return getTermByUuid(uuidSubsubform);
380
	}
381
	/**
382
	 * 'Unranked infraspecific'. An infraspecific rank which is on purpose not further defined.
383
	 * This sometimes holds for names from the 19th century. 
384
	 */
385
	public static final Rank INFRASPECIFICTAXON(){
386
		return getTermByUuid(uuidInfraspecificTaxon);
387
	}
388
	public static final Rank CANDIDATE(){
389
		return getTermByUuid(uuidCandidate);
390
	}
391
	public static final Rank DENOMINATIONCLASS(){
392
		return getTermByUuid(uuidDenominationClass);
393
	}
394
	public static final Rank GREX(){
395
		return getTermByUuid(uuidGrex);
396
	}
397
	public static final Rank GRAFTCHIMAERA(){
398
		return getTermByUuid(uuidGraftChimaera);
399
	}
400
	public static final Rank CULTIVARGROUP(){
401
		return getTermByUuid(uuidCultivarGroup);
402
	}
403
	public static final Rank CULTIVAR(){
404
		return getTermByUuid(uuidCultivar);
405
	}
406
	public static final Rank UNKNOWN_RANK(){
407
		return getTermByUuid(uuidUnknownRank);
408
	}
409
	public static final Rank NATIO(){
410
		return getTermByUuid(uuidNatio);
411
	}
412
	/**
413
	 * @see #INFRASPECIFICTAXON()
414
	 */
415
	public static final Rank UNRANKED_INFRASPECIFIC(){
416
		return getTermByUuid(uuidInfraspecificTaxon);
417
	}
418
	/**
419
	 * @see #INFRAGENERICTAXON()
420
	 */
421
	public static final Rank UNRANKED_INFRAGENERIC(){
422
		return getTermByUuid(uuidInfragenericTaxon);
423
	}
424
	
425
	/**
426
	 * Returns the boolean value indicating whether <i>this</i> rank is higher than 
427
	 * the genus rank (true) or not (false). Returns false if <i>this</i> rank is null.
428
	 *
429
	 * @see  #isGenus()
430
	 * @see  #isInfraGeneric()
431
	 * @see  #isSpecies()
432
	 * @see  #isInfraSpecific()
433
	 */
434
	@Transient
435
	public boolean isSupraGeneric(){
436
		return (this.isHigher(Rank.GENUS()));
437
	}
438
	
439
	/**
440
	 * Returns the boolean value indicating whether <i>this</i> rank is the genus rank
441
	 * (true) or not (false). Returns false if <i>this</i> rank is null.
442
	 *
443
	 * @see  #isSupraGeneric()
444
	 * @see  #isInfraGeneric()
445
	 * @see  #isSpecies()
446
	 * @see  #isInfraSpecific()
447
	 */
448
	@Transient
449
	public boolean isGenus(){
450
		return (this.equals(Rank.GENUS()));
451
	}
452

    
453
	/**
454
	 * Returns the boolean value indicating whether <i>this</i> rank is higher than the
455
	 * species rank and lower than the genus rank (true) or not (false). Species groups or
456
	 * aggregates are also handled as infrageneric ranks.
457
	 * Returns false if <i>this</i> rank is null.
458
	 *
459
	 * @see  #isSupraGeneric()
460
	 * @see  #isGenus()
461
	 * @see  #isSpeciesAggregate()
462
	 * @see  #isSpecies()
463
	 * @see  #isInfraSpecific()
464
	 */
465
	@Transient
466
	public boolean isInfraGeneric(){
467
		return (this.isLower(Rank.GENUS()) && this.isHigher(Rank.SPECIES()));
468
	}
469

    
470
	/**
471
	 * Returns true if this rank indicates a rank that aggregates species
472
	 * like species aggregates or species groups, false otherwise. This methods 
473
	 * currently returns false for all user defined ranks.
474
	 * @return
475
	 */
476
	@Transient
477
	public boolean isSpeciesAggregate(){
478
		return (this.equals(Rank.SPECIESAGGREGATE()) || (this.isLower(Rank.SPECIESAGGREGATE()) && this.isHigher(Rank.SPECIES())));
479
	}	
480
	
481
	/**
482
	 * Returns the boolean value indicating whether <i>this</i> rank is the species
483
	 * rank (true) or not (false). Returns false if <i>this</i> rank is null.
484
	 *
485
	 * @see  #isSupraGeneric()
486
	 * @see  #isGenus()
487
	 * @see  #isInfraGeneric()
488
	 * @see  #isInfraSpecific()
489
	 */
490
	@Transient
491
	public boolean isSpecies(){
492
		return (this.equals(Rank.SPECIES()));
493
	}
494

    
495
	/**
496
	 * Returns the boolean value indicating whether <i>this</i> rank is lower than the
497
	 * species rank (true) or not (false). Returns false if <i>this</i> rank is null.
498
	 *
499
	 * @see  #isSupraGeneric()
500
	 * @see  #isGenus()
501
	 * @see  #isInfraGeneric()
502
	 * @see  #isSpecies()
503
	 */
504
	@Transient
505
	public boolean isInfraSpecific(){
506
		return (this.isLower(Rank.SPECIES()));
507
	}
508

    
509

    
510
	/**
511
	 * Returns the rank identified through a name (abbreviated or not).
512
	 * Preliminary implementation for BotanicalNameParser.
513
	 * 
514
	 * @param	strRank	the string identifying the rank
515
	 * @return  		the rank
516
	 */
517
	public static Rank getRankByNameOrAbbreviation(String strRank)
518
				throws UnknownCdmTypeException{
519
		return getRankByNameOrAbbreviation(strRank, false);
520
	}
521

    
522
	/**
523
	 * Returns the rank identified through a name (abbreviated or not) for a given nomenclatural code.
524
	 * Preliminary implementation for BotanicalNameParser.
525
	 * 
526
	 * @param	strRank	the string identifying the rank
527
	 * @param   nc      the nomenclatural code
528
	 * @return  		the rank
529
	 */
530
	public static Rank getRankByNameOrAbbreviation(String strRank, NomenclaturalCode nc)
531
				throws UnknownCdmTypeException{
532
		return getRankByNameOrAbbreviation(strRank, nc, false);
533
	}
534
	
535
	// TODO
536
	// Preliminary implementation for BotanicalNameParser.
537
	// not yet complete
538
	/**
539
	 * Returns the rank identified through a name (abbreviated or not).
540
	 * Preliminary implementation for BotanicalNameParser.
541
	 * 
542
	 * @param	strRank	the string identifying the rank
543
	 * @param 	useUnknown 	if true the rank UNKNOWN_RANK is returned if the abbrev is 
544
	 * 			unknown or not yet implemented
545
	 * @return  		the rank
546
	 */
547
	public static Rank getRankByNameOrAbbreviation(String strRank, boolean useUnknown)
548
			throws UnknownCdmTypeException{
549
		try {
550
			return getRankByAbbreviation(strRank);
551
		} catch (UnknownCdmTypeException e) {
552
			return getRankByName(strRank, useUnknown);
553
		}
554
	}
555
	
556
	// TODO
557
	// Preliminary implementation for BotanicalNameParser.
558
	// not yet complete
559
	/**
560
	 * Returns the rank identified through a name (abbreviated or not).
561
	 * Preliminary implementation for BotanicalNameParser.
562
	 * 
563
	 * @param	strRank	the string identifying the rank
564
	 * @param   nc      the nomenclatural code
565
	 * @param 	useUnknown 	if true the rank UNKNOWN_RANK is returned if the abbrev is 
566
	 * 			unknown or not yet implemented
567
	 * @return  		the rank
568
	 */
569
	public static Rank getRankByNameOrAbbreviation(String strRank, NomenclaturalCode nc, boolean useUnknown)
570
			throws UnknownCdmTypeException{
571
		try {
572
			return getRankByAbbreviation(strRank, nc);
573
		} catch (UnknownCdmTypeException e) {
574
			return getRankByName(strRank, nc, useUnknown);
575
		}
576
	}
577
	
578
	/**
579
	 * Returns the rank identified through an abbreviated name.
580
	 * Preliminary implementation for BotanicalNameParser.<BR>
581
	 * Note: For abbrev = "[unranked]" the result is undefined.
582
	 * It maybe the infrageneric unranked or the infraspecific unranked.
583
	 * You need to define by context which one is correct.
584
	 * 
585
	 * @param	abbrev	the string for the name abbreviation
586
	 * @return  		the rank
587
	 */
588
	public static Rank getRankByAbbreviation(String abbrev) 
589
						throws UnknownCdmTypeException{
590
		return getRankByAbbreviation(abbrev, false);
591
	}
592
	
593
	/**
594
	 * Returns the rank identified through an abbreviated name for a given nomenclatural code.
595
	 * See also {@link #getRankByAbbreviation(String, boolean)}
596
	 * 
597
	 * @param	abbrev	the string for the name abbreviation
598
	 * @param	nc	    the nomenclatural code
599
	 * @return  		the rank
600
	 */
601
	public static Rank getRankByAbbreviation(String abbrev, NomenclaturalCode nc) throws UnknownCdmTypeException{
602
		return getRankByAbbreviation(abbrev, nc, false);
603
	}
604
	
605
	// TODO
606
	// Preliminary implementation for BotanicalNameParser.
607
	// not yet complete
608
	/**
609
	 * Returns the rank identified through an abbreviated representation.
610
	 * At the moment it uses the English abbreviations (being Latin because 
611
	 * we do not have Latin representations yet.
612
	 * TODO
613
	 * If no according abbreviation is available it throws either an UnknownCdmTypeException
614
	 * or an #Rank.UNKNOWN() object depending on the useUnknown flag. 
615
	 * 
616
	 * @param	abbrev		the string for the name abbreviation
617
	 * @param 	useUnknown 	if true the rank UNKNOWN_RANK is returned if the abbrev is 
618
	 * 			unknown or not yet existent
619
	 * @return  the rank
620
	 */
621
	public static Rank getRankByAbbreviation(String abbrev, boolean useUnknown) throws UnknownCdmTypeException{
622
		Rank result = null;
623
		if (abbrev == null){ 
624
			throw new NullPointerException("Abbrev is NULL in getRankByAbbreviation");
625
		}
626
		if (abbrev.trim().equals("")){
627
			//handle empty abbrev as unknown
628
			abbrev = "oija?m??";
629
		}
630
		if (abbrevMap == null){
631
			return null;
632
		}
633
		UUID uuid = abbrevMap.get(abbrev);
634
		if (uuid != null ){
635
			result = getTermByUuid(uuid);
636
		}
637
		if (result != null){
638
			return result;
639
		}else { 
640
			if (abbrev == null){
641
				abbrev = "(null)";
642
			}
643
			if (useUnknown){
644
				logger.info("Unknown rank name: " + abbrev + ". Rank 'UNKNOWN_RANK' created instead");
645
				return Rank.UNKNOWN_RANK();
646
			}else{
647
				throw new UnknownCdmTypeException("Unknown rank abbreviation: " + abbrev);
648
			}
649
		}
650
	}
651
	
652
	// TODO
653
	// Preliminary implementation to cover Botany and Zoology.
654
	/**
655
	 * Returns the rank identified through an abbreviated name for a given nomenclatural code.
656
	 * Preliminary implementation for ICBN and ICZN.
657
	 * See also {@link #getRankByAbbreviation(String, boolean)}
658

    
659
	 * 
660
	 * @param	abbrev		the string for the name abbreviation
661
	 * @param	nc	        the nomenclatural code
662
	 * @param 	useUnknown 	if true the rank UNKNOWN_RANK is returned if the abbrev is 
663
	 * 			unknown or not yet implemented
664
	 * @return  the rank
665
	 */
666
	public static Rank getRankByAbbreviation(String abbrev, NomenclaturalCode nc,  boolean useUnknown) 
667
		throws UnknownCdmTypeException{
668
		
669
		if (nc != null && nc.equals(NomenclaturalCode.ICZN)) {
670
			if (abbrev.equalsIgnoreCase("sect.")) { return Rank.SECTION_ZOOLOGY();
671
			} else if (abbrev.equalsIgnoreCase("subsect.")) { return Rank.SUBSECTION_ZOOLOGY();
672
			}
673
		}
674
		return getRankByAbbreviation(abbrev, useUnknown);
675
	}
676
	
677
	// TODO
678
	// Preliminary implementation for BotanicalNameParser.
679
	// not yet complete
680
	/**
681
	 * Returns the rank identified through a name.
682
	 * Preliminary implementation for BotanicalNameParser.
683
	 * 
684
	 * @param	rankName	the string for the name of the rank
685
	 * @return  			the rank
686
	 */
687
	public static Rank getRankByName(String rankName) throws UnknownCdmTypeException{
688
		return getRankByName(rankName, false);
689
	}
690
	
691

    
692
	// TODO
693
	// Preliminary implementation for ICBN and ICZN.
694
	// not yet complete
695
	/**
696
	 * Returns the rank identified through a name for a given nomenclatural code.
697
	 * Preliminary implementation for ICBN and ICZN.
698
	 * 
699
	 * @param	rankName	the string for the name of the rank
700
	 * @param	nc	        the nomenclatural code
701
	 * @return  			the rank
702
	 */
703
	public static Rank getRankByName(String rankName, NomenclaturalCode nc) throws UnknownCdmTypeException{
704
		return getRankByName(rankName, nc, false);
705
	}
706

    
707
	/**
708
	 * Returns the rank identified through a name.
709
	 * Preliminary implementation for BotanicalNameParser.
710
	 * TODO At the moment we do not have Latin representations yet.
711
	 * 
712
	 * @param	rankName	the string for the name of the rank
713
	 * @param 	useUnknown 	if true the rank UNKNOWN_RANK is returned if the rank name is 
714
	 * 			unknown or not yet implemented
715
	 * @return  			the rank
716
	 */
717
	public static Rank getRankByName(String rankName, boolean useUnknown)
718
			throws UnknownCdmTypeException{
719
		if (rankName.equalsIgnoreCase("Regnum")){ return Rank.KINGDOM();
720
		}else if (rankName.equalsIgnoreCase("Subregnum")){ return Rank.SUBKINGDOM();
721
		}else if (rankName.equalsIgnoreCase("Phylum")){ return Rank.PHYLUM();
722
		}else if (rankName.equalsIgnoreCase("Subphylum")){ return Rank.SUBPHYLUM();
723
		}else if (rankName.equalsIgnoreCase("Divisio")){ return Rank.DIVISION();
724
		}else if (rankName.equalsIgnoreCase("Subdivisio")){ return Rank.SUBDIVISION();
725
		}else if (rankName.equalsIgnoreCase("Classis")){ return Rank.CLASS();
726
		}else if (rankName.equalsIgnoreCase("Subclassis")){ return Rank.SUBCLASS();
727
		}else if (rankName.equalsIgnoreCase("Superordo")){ return Rank.SUPERORDER();
728
		}else if (rankName.equalsIgnoreCase("Ordo")){ return Rank.ORDER();
729
		}else if (rankName.equalsIgnoreCase("Subordo")){ return Rank.SUBORDER();
730
		}else if (rankName.equalsIgnoreCase("Familia")){ return Rank.FAMILY();
731
		}else if (rankName.equalsIgnoreCase("Subfamilia")){ return Rank.SUBFAMILY();
732
		}else if (rankName.equalsIgnoreCase("Tribus")){ return Rank.TRIBE();
733
		}else if (rankName.equalsIgnoreCase("Subtribus")){ return Rank.SUBTRIBE();
734
		}else if (rankName.equalsIgnoreCase("Genus")){ return Rank.GENUS();
735
		}else if (rankName.equalsIgnoreCase("Subgenus")){ return Rank.SUBGENUS();
736
		}else if (rankName.equalsIgnoreCase("Sectio")){ return Rank.SECTION_BOTANY();
737
		}else if (rankName.equalsIgnoreCase("Subsectio")){ return Rank.SUBSECTION_BOTANY();
738
		}else if (rankName.equalsIgnoreCase("Series")){ return Rank.SERIES();
739
		}else if (rankName.equalsIgnoreCase("Subseries")){ return Rank.SUBSERIES();
740
		}else if (rankName.equalsIgnoreCase("Aggregate")){ return Rank.SPECIESAGGREGATE();
741
		}else if (rankName.equalsIgnoreCase("Speciesgroup")){ return Rank.SPECIESGROUP();
742
		}else if (rankName.equalsIgnoreCase("Species")){ return Rank.SPECIES();
743
		}else if (rankName.equalsIgnoreCase("Subspecies")){ return Rank.SUBSPECIES();
744
		}else if (rankName.equalsIgnoreCase("Convarietas")){ return Rank.CONVAR();
745
		}else if (rankName.equalsIgnoreCase("Varietas")){ return Rank.VARIETY();
746
		}else if (rankName.equalsIgnoreCase("Subvarietas")){ return Rank.SUBVARIETY();
747
		}else if (rankName.equalsIgnoreCase("Forma")){ return Rank.FORM();
748
		}else if (rankName.equalsIgnoreCase("Subforma")){ return Rank.SUBFORM();
749
		}else if (rankName.equalsIgnoreCase("Forma spec.")){ return Rank.SPECIALFORM();
750
		}else if (rankName.equalsIgnoreCase("tax.infragen.")){ return Rank.INFRAGENERICTAXON();
751
		}else if (rankName.equalsIgnoreCase("tax.infrasp.")){ return Rank.INFRASPECIFICTAXON();
752
		// old ranks 
753
		}else if (rankName.equalsIgnoreCase("proles")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
754
		}else if (rankName.equalsIgnoreCase("race")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
755
		}else if (rankName.equalsIgnoreCase("taxon")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
756
		}else if (rankName.equalsIgnoreCase("sublusus")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
757
		
758
		}else{ 
759
			if (rankName == null){
760
				rankName = "(null)";  //see NPE above
761
			}
762
			if (useUnknown){
763
				logger.info("Unknown rank name: " + rankName+". Rank 'UNKNOWN_RANK' created instead");
764
				return Rank.UNKNOWN_RANK();
765
			}else{
766
				throw new UnknownCdmTypeException("Unknown rank name: " + rankName);
767
			}
768
		}
769
	}
770

    
771
	/**
772
	 * Defines the rank according to the English name.
773
	 * @param rankName English rank name.
774
	 * @param nc Defines the handling of the section and subsection ranks. These are in different orders depending on the
775
	 * nomenclatural code.
776
	 * @param useUnknown if true, the "Unknown" rank is returned as a placeholder.
777
	 * @return
778
	 * @throws UnknownCdmTypeException never thrown if useUnknown is true
779
	 */
780
	public static Rank getRankByEnglishName(String rankName, NomenclaturalCode nc, boolean useUnknown) throws UnknownCdmTypeException{
781
		Rank result = null;
782
		if (rankName == null){ 
783
			throw new NullPointerException("Abbrev is NULL in getRankByAbbreviation");
784
		}
785
		if (labelMap == null){
786
			return null;
787
		}
788
		//handle section and subsection (not unique representations)
789
		if (rankName.equalsIgnoreCase("Section")){ 
790
			if (nc != null && nc.equals(NomenclaturalCode.ICZN)){	return Rank.SECTION_ZOOLOGY();
791
			}else if (nc != null && nc.equals(NomenclaturalCode.ICBN)){return Rank.SECTION_BOTANY();
792
			}else{
793
				String errorWarning = "Section is only defined for ICZN and ICBN at the moment but here needed for " + ((nc == null)? "(null)": nc.toString());
794
				logger.warn(errorWarning);
795
				throw new UnknownCdmTypeException (errorWarning);
796
			}
797
		}else if (rankName.equalsIgnoreCase("Subsection")){ 
798
			if (nc != null && nc.equals(NomenclaturalCode.ICZN)){ return Rank.SECTION_ZOOLOGY();
799
			}else if (nc != null && nc.equals(NomenclaturalCode.ICBN)){ return Rank.SECTION_BOTANY();
800
			}else{
801
				String errorWarning = "Subsection is only defined for ICZN and ICBN at the moment but here needed for " + ((nc == null)? "(null)": nc.toString());
802
				logger.warn(errorWarning);
803
				throw new UnknownCdmTypeException (errorWarning);
804
			}
805
		}
806
		
807
		rankName = rankName.toLowerCase();
808
		
809
		UUID uuid = labelMap.get(rankName);
810
		if (uuid != null ){
811
			result = getTermByUuid(uuid);
812
		}
813
		if (result != null){
814
			return result;
815
		}else { 
816
			if (rankName == null){
817
				rankName = "(null)";
818
			}
819
			if (useUnknown){
820
				logger.info("Unknown rank name: " + rankName + ". Rank 'UNKNOWN_RANK' created instead");
821
				return Rank.UNKNOWN_RANK();
822
			}else{
823
				throw new UnknownCdmTypeException("Unknown rank: " + rankName);
824
			}
825
		}
826
	}
827

    
828
	
829
	public static Rank getRankByName(String rankName, NomenclaturalCode nc, boolean useUnknown)
830
		throws UnknownCdmTypeException {
831
		
832
		if (nc.equals(NomenclaturalCode.ICZN)) {
833
			if (rankName.equalsIgnoreCase("Sectio")) { return Rank.SECTION_ZOOLOGY();
834
			}else if (rankName.equalsIgnoreCase("Subsectio")) { return Rank.SUBSECTION_ZOOLOGY();
835
			}
836
		}
837
		return getRankByName(rankName, useUnknown);
838
	}
839
	
840
	/**
841
	 * Returns the abbreviated rank name for <i>this</i> rank according to the English representation
842
	 * abbreviated label. 
843
	 * TODO Needs to be changed to Latin as soon as Latin representations are available.
844
	 * 
845
	 * @return	the abbreviation string for <i>this</i> rank
846
	 */
847
	public String getAbbreviation(){
848
		Language language = Language.ENGLISH();
849
		String result = this.getRepresentation(language).getAbbreviatedLabel();
850
		if (result== null) {
851
			logger.warn("Abbreviation for this Rank " + this.toString() +  " not yet implemented");
852
			return "no abbreviation available.";
853
		}else{
854
			return result;
855
		}
856
	}
857
	@Transient
858
	public String getInfraGenericMarker() throws UnknownCdmTypeException{
859
		String result = null;
860
		if (! this.isInfraGeneric()){
861
			throw new IllegalStateException("An infrageneric marker is only available for a infrageneric rank but was asked for rank: " + this.toString());
862
		}else{
863
			result = this.getAbbreviation();
864
		}
865
		if (result == null){
866
			throw new UnknownCdmTypeException("Abbreviation for rank unknown: " + this.toString());
867
		}
868
		return result;
869
	}
870
	
871
	
872

    
873
	@Override
874
	public Rank readCsvLine(Class<Rank> termClass, List<String> csvLine, Map<UUID, DefinedTermBase> terms) {
875
		return super.readCsvLine(termClass, csvLine, terms);
876
	}
877

    
878
	@Override
879
	protected void setDefaultTerms(TermVocabulary<Rank> termVocabulary) {
880
		termMap = new HashMap<UUID, Rank>();
881
		for (Rank term : termVocabulary.getTerms()){
882
			termMap.put(term.getUuid(), (Rank)term);
883
			addRank(term);
884
		}
885
	}
886

    
887
	/**
888
	 * @param term
889
	 */
890
	private void addRank(Rank rank) {
891
		if (rank == null){
892
			logger.warn("rank is NULL");
893
			return;
894
		}
895
		if (rank.getUuid().equals(uuidSectionZoology) || rank.getUuid().equals(uuidSubsectionZoology )){
896
			//sect./subsect. is used for botanical sections, see also #getRankByAbbreviation(String, NomenclaturalCode, boolean)
897
			return;
898
		}
899
		Language lang = Language.DEFAULT();  //TODO should be Latin but at the moment we have only English representations 
900
		Representation representation = rank.getRepresentation(lang);
901
		String abbrevLabel = representation.getAbbreviatedLabel();
902
		String label = representation.getLabel();
903
		if (abbrevLabel == null){
904
			logger.warn("label is NULL");
905
			return;
906
		}
907
		//initialize maps
908
		if (abbrevMap == null){
909
			abbrevMap = new HashMap<String, UUID>();
910
		}
911
		if (labelMap == null){
912
			labelMap = new HashMap<String, UUID>();
913
		}
914
		//add to map
915
		abbrevMap.put(abbrevLabel, rank.getUuid());
916
		labelMap.put(label.toLowerCase(), rank.getUuid());	
917
	}
918
	
919
	
920
	/**
921
	 * It is nessecary to skip the vocabulary check, otherwise we would have
922
	 * problems in some CacheStrategies, due to uninitialized Vocabularies.
923
	 * 
924
	 * @see eu.etaxonomy.cdm.model.common.OrderedTermBase#compareTo(eu.etaxonomy.cdm.model.common.OrderedTermBase)
925
	 */
926
	@Override
927
	public int compareTo(Rank orderedTerm) {
928
		return performCompareTo(orderedTerm, true);
929
	}
930

    
931
}
(16-16/26)