AT: committing CDMLIB to Branch post Merge
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / Rank.java
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.common.CdmUtils;
28 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
29 import eu.etaxonomy.cdm.model.common.Language;
30 import eu.etaxonomy.cdm.model.common.OrderedTermBase;
31 import eu.etaxonomy.cdm.model.common.Representation;
32 import eu.etaxonomy.cdm.model.common.TermVocabulary;
33 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
34
35 /**
36 * The class representing the taxonomical ranks (like "Family", "Genus" or
37 * "Species") used for {@link TaxonNameBase taxon names} across all {@link NomenclaturalCode nomenclatural codes}
38 * for bacteria (ICNB), viruses (ICVCN), plants and fungi (ICBN),
39 * cultivars (ICNCP) and animals (ICZN).
40 * <P>
41 * A standard (ordered) list of taxonomical rank instances will be automatically
42 * created as the project starts. But this class allows to extend this standard
43 * list by creating new instances of additional taxonomical ranks if needed.
44 * <P>
45 * This class corresponds to: <ul>
46 * <li> TaxonRankTerm according to the TDWG ontology
47 * <li> TaxonomicRankEnum according to the TCS
48 * <li> Rank according to the ABCD schema
49 * </ul>
50 *
51 * @author m.doering
52 * @version 1.0
53 * @created 08-Nov-2007 13:06:46
54 */
55 @XmlAccessorType(XmlAccessType.FIELD)
56 @XmlType(name = "Rank")
57 @Entity
58 @Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
59 @Audited
60 public class Rank extends OrderedTermBase<Rank> {
61 private static final long serialVersionUID = -8648081681348758485L;
62 private static final Logger logger = Logger.getLogger(Rank.class);
63
64 private static final UUID uuidEmpire = UUID.fromString("ac470211-1586-4b24-95ca-1038050b618d");
65 private static final UUID uuidDomain = UUID.fromString("ffca6ec8-8b88-417b-a6a0-f7c992aac19b");
66 private static final UUID uuidSuperkingdom = UUID.fromString("64223610-7625-4cfd-83ad-b797bf7f0edd");
67 private static final UUID uuidKingdom = UUID.fromString("fbe7109d-66b3-498c-a697-c6c49c686162");
68 private static final UUID uuidSubkingdom = UUID.fromString("a71bd9d8-f3ab-4083-afb5-d89315d71655");
69 private static final UUID uuidInfrakingdom = UUID.fromString("1e37930c-86cf-44f6-90fd-7822928df260");
70 private static final UUID uuidSuperphylum = UUID.fromString("0d0cecb1-e254-4607-b210-6801e7ecbb04");
71 private static final UUID uuidPhylum = UUID.fromString("773430d2-76b4-438c-b817-97a543a33287");
72 private static final UUID uuidSubphylum = UUID.fromString("23a9b6ff-9408-49c9-bd9e-7a2ca5ab4725");
73 private static final UUID uuidInfraphylum = UUID.fromString("1701de3a-7693-42a5-a2d3-42697f944190");
74 private static final UUID uuidSuperdivision = UUID.fromString("a735a48f-4fc8-49a7-ae0c-6a984f658131");
75 private static final UUID uuidDivision = UUID.fromString("7e56f5cc-123a-4fd1-8cbb-6fd80358b581");
76 private static final UUID uuidSubdivision = UUID.fromString("931c840f-7a6b-4d76-ad38-bfdd77d7b2e8");
77 private static final UUID uuidInfradivision = UUID.fromString("c0ede273-be52-4dee-b411-66ee08d30c94");
78 private static final UUID uuidSuperclass = UUID.fromString("e65b4e1a-21ec-428d-9b9f-e87721ab967c");
79 private static final UUID uuidClass = UUID.fromString("f23d14c4-1d34-4ee6-8b4e-eee2eb9a3daf");
80 private static final UUID uuidSubclass = UUID.fromString("8cb26733-e2f5-46cb-ab5c-f99254f877aa");
81 private static final UUID uuidInfraclass = UUID.fromString("ad23cfda-879a-4021-8629-c54d27caf717");
82 private static final UUID uuidSuperorder = UUID.fromString("c8c67a22-301a-4219-b882-4a49121232ff");
83 private static final UUID uuidOrder = UUID.fromString("b0785a65-c1c1-4eb4-88c7-dbd3df5aaad1");
84 private static final UUID uuidSuborder = UUID.fromString("768ad378-fa85-42ab-b668-763225832f57");
85 private static final UUID uuidInfraorder = UUID.fromString("84099182-a6f5-47d7-8586-33c9e9955a10");
86 private static final UUID uuidSectionZoology = UUID.fromString("691d371e-10d7-43f0-93db-3d7fa1a62c54");
87 private static final UUID uuidSubsectionZoology = UUID.fromString("0ed32d28-adc4-4303-a9ca-68e2acd67e33");
88 private static final UUID uuidSuperfamily = UUID.fromString("2cfa510a-dcea-4a03-b66a-b1528f9b0796");
89 private static final UUID uuidFamily = UUID.fromString("af5f2481-3192-403f-ae65-7c957a0f02b6");
90 private static final UUID uuidSubfamily = UUID.fromString("862526ee-7592-4760-a23a-4ff3641541c5");
91 private static final UUID uuidInfrafamily = UUID.fromString("c3f2e3bb-6eef-4a26-9fb7-b14f4c8c5e4f");
92 private static final UUID uuidSupertribe = UUID.fromString("11e94828-8c61-499b-87d6-1de35ce2c51c");
93 private static final UUID uuidTribe = UUID.fromString("4aa6890b-0363-4899-8d7c-ee0cb78e6166");
94 private static final UUID uuidSubtribe = UUID.fromString("ae41ecc5-5165-4126-9d24-79939ae5d822");
95 private static final UUID uuidInfratribe = UUID.fromString("1ec02e8f-f2b7-4c65-af9f-b436b34c79a3");
96 private static final UUID uuidSupragenericTaxon = UUID.fromString("1fdc0b93-c354-441a-8406-091e0303ff5c");
97 public static final UUID uuidGenus = UUID.fromString("1b11c34c-48a8-4efa-98d5-84f7f66ef43a");
98 private static final UUID uuidSubgenus = UUID.fromString("78786e16-2a70-48af-a608-494023b91904");
99 private static final UUID uuidInfragenus = UUID.fromString("a9972969-82cd-4d54-b693-a096422f13fa");
100 private static final UUID uuidSectionBotany = UUID.fromString("3edff68f-8527-49b5-bf91-7e4398bb975c");
101 private static final UUID uuidSubsectionBotany = UUID.fromString("d20f5b61-d463-4448-8f8a-c1ff1f262f59");
102 private static final UUID uuidSeries = UUID.fromString("d7381ecf-48f8-429b-9c54-f461656978cd");
103 private static final UUID uuidSubseries = UUID.fromString("80c9a263-f4db-4a13-b6c2-b7fec1aa1200");
104 private static final UUID uuidSpeciesAggregate = UUID.fromString("1ecae058-4217-4f75-9c27-6d8ba099ac7a");
105 private static final UUID uuidSpeciesGroup = UUID.fromString("d1988a11-292b-46fa-8fb7-bc64ea6d8fc6");
106 private static final UUID uuidInfragenericTaxon = UUID.fromString("41bcc6ac-37d3-4fd4-bb80-3cc5b04298b9");
107 public static final UUID uuidSpecies = UUID.fromString("b301f787-f319-4ccc-a10f-b4ed3b99a86d");
108 private static final UUID uuidSubspecificAggregate = UUID.fromString("72c248b9-027d-4402-b375-dd4f0850c9ad");
109 private static final UUID uuidSubspecies = UUID.fromString("462a7819-8b00-4190-8313-88b5be81fad5");
110 private static final UUID uuidInfraspecies = UUID.fromString("f28ebc9e-bd50-4194-9af1-42f5cb971a2c");
111 private static final UUID uuidNatio = UUID.fromString("965f2f38-7f97-4270-ab5a-1999bf050a22");
112 private static final UUID uuidVariety = UUID.fromString("d5feb6a5-af5c-45ef-9878-bb4f36aaf490");
113 private static final UUID uuidBioVariety = UUID.fromString("a3a364cb-1a92-43fc-a717-3c44980a0991");
114 private static final UUID uuidPathoVariety = UUID.fromString("2f4f4303-a099-47e3-9048-d749d735423b");
115 private static final UUID uuidSubvariety = UUID.fromString("9a83862a-7aee-480c-a98d-4bceaf8712ca");
116 private static final UUID uuidSubsubvariety = UUID.fromString("bff22f84-553a-4429-a4e7-c4b3796c3a18");
117 private static final UUID uuidConvar = UUID.fromString("2cc740c9-cebb-43c8-9b06-1bef79e6a56a");
118 private static final UUID uuidForm = UUID.fromString("0461281e-458a-47b9-8d41-19a3d39356d5");
119 private static final UUID uuidSpecialForm = UUID.fromString("bed20aee-2f5a-4635-9c02-eff06246d067");
120 private static final UUID uuidSubform = UUID.fromString("47cfc5b0-0fb7-4ceb-b61d-e1dd8de8b569");
121 private static final UUID uuidSubsubform = UUID.fromString("1c8ac389-4349-4ae0-87be-7239f6635068");
122 private static final UUID uuidInfraspecificTaxon = UUID.fromString("eb75c27d-e154-4570-9d96-227b2df60474");
123 private static final UUID uuidCandidate = UUID.fromString("ead9a1f5-dfd4-4de2-9121-70a47accb10b");
124 private static final UUID uuidDenominationClass = UUID.fromString("49bdf74a-2170-40ed-8be2-887a0db517bf");
125 private static final UUID uuidGrex = UUID.fromString("08dcb4ff-ac58-48a3-93af-efb3d836ac84");
126 private static final UUID uuidGraftChimaera = UUID.fromString("6b4063bc-f934-4796-9bf3-0ef3aea5c1cb");
127 private static final UUID uuidCultivarGroup = UUID.fromString("d763e7d3-e7de-4bb1-9d75-225ca6948659");
128 private static final UUID uuidCultivar = UUID.fromString("5e98415b-dc6e-440b-95d6-ea33dbb39ad0");
129 private static final UUID uuidUnknownRank = UUID.fromString("5c4d6755-2cf6-44ca-9220-cccf8881700b");
130 // private static final UUID uuidUnrankedInfraSpecific = UUID.fromString("a965befb-70a9-4747-a18f-624456c65223");
131 // private static final UUID uuidUnrankedInfraGeneric = UUID.fromString("994646a1-c2e7-461d-a1bc-2afd6ea51b40");
132
133 private static Map<String, UUID> abbrevMap = null;
134 private static Map<String, UUID> labelMap = null;
135
136 protected static Map<UUID, Rank> termMap = null;
137
138 //*********************** Factory methods ********************************************/
139
140 /**
141 * Creates a new empty rank.
142 *
143 * @see #NewInstance(String, String, String)
144 */
145 private static Rank NewInstance(){
146 return new Rank();
147 }
148
149 /**
150 * Creates an additional rank with a description (in the {@link Language#DEFAULT() default language}),
151 * a label and a label abbreviation.
152 *
153 * @param term the string (in the default language) describing the
154 * new rank to be created
155 * @param label the string identifying the new rank to be created
156 * @param labelAbbrev the string identifying (in abbreviated form) the
157 * new rank to be created
158 * @see #NewInstance()
159 */
160 private static Rank NewInstance(String term, String label, String labelAbbrev){
161 return new Rank(term, label, labelAbbrev);
162 }
163
164 // ********************* CONSTRUCTORS ************************************+/
165 /**
166 * Class constructor: creates a new empty rank instance.
167 *
168 * @see #Rank(String, String, String)
169 */
170 public Rank() {
171 }
172
173 /**
174 * Class constructor: creates an additional rank instance with a description
175 * (in the {@link eu.etaxonomy.cdm.model.common.Language#DEFAULT() default language}), a label and a label abbreviation.
176 *
177 * @param term the string (in the default language) describing the
178 * new rank to be created
179 * @param label the string identifying the new rank to be created
180 * @param labelAbbrev the string identifying (in abbreviated form) the
181 * new rank to be created
182 * @see #Rank()
183 */
184 public Rank(String term, String label, String labelAbbrev) {
185 super(term, label, labelAbbrev);
186 }
187
188
189 //********* METHODS **************************************/
190
191 /* (non-Javadoc)
192 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#resetTerms()
193 */
194 @Override
195 public void resetTerms(){
196 termMap = null;
197 }
198
199
200
201 protected static Rank getTermByUuid(UUID uuid){
202 if (termMap == null){
203 return null; //better return null then initialize the termMap in an unwanted way
204 }
205 return (Rank)termMap.get(uuid);
206 }
207
208 public static final Rank EMPIRE(){
209 return getTermByUuid(uuidEmpire);
210 }
211 public static final Rank DOMAIN(){
212 return getTermByUuid(uuidDomain);
213 }
214 public static final Rank SUPERKINGDOM(){
215 return getTermByUuid(uuidSuperkingdom);
216 }
217 public static final Rank KINGDOM(){
218 return getTermByUuid(uuidKingdom);
219 }
220 public static final Rank SUBKINGDOM(){
221 return getTermByUuid(uuidSubkingdom);
222 }
223 public static final Rank INFRAKINGDOM(){
224 return getTermByUuid(uuidInfrakingdom);
225 }
226 public static final Rank SUPERPHYLUM(){
227 return getTermByUuid(uuidSuperphylum);
228 }
229 public static final Rank PHYLUM(){
230 return getTermByUuid(uuidPhylum);
231 }
232 public static final Rank SUBPHYLUM(){
233 return getTermByUuid(uuidSubphylum);
234 }
235 public static final Rank INFRAPHYLUM(){
236 return getTermByUuid(uuidInfraphylum);
237 }
238 public static final Rank SUPERDIVISION(){
239 return getTermByUuid(uuidSuperdivision);
240 }
241 public static final Rank DIVISION(){
242 return getTermByUuid(uuidDivision);
243 }
244 public static final Rank SUBDIVISION(){
245 return getTermByUuid(uuidSubdivision);
246 }
247 public static final Rank INFRADIVISION(){
248 return getTermByUuid(uuidInfradivision);
249 }
250 public static final Rank SUPERCLASS(){
251 return getTermByUuid(uuidSuperclass);
252 }
253 public static final Rank CLASS(){
254 return getTermByUuid(uuidClass);
255 }
256 public static final Rank SUBCLASS(){
257 return getTermByUuid(uuidSubclass);
258 }
259 public static final Rank INFRACLASS(){
260 return getTermByUuid(uuidInfraclass);
261 }
262 public static final Rank SUPERORDER(){
263 return getTermByUuid(uuidSuperorder);
264 }
265 public static final Rank ORDER(){
266 return getTermByUuid(uuidOrder);
267 }
268 public static final Rank SUBORDER(){
269 return getTermByUuid(uuidSuborder);
270 }
271 public static final Rank INFRAORDER(){
272 return getTermByUuid(uuidInfraorder);
273 }
274 public static final Rank SUPERFAMILY(){
275 return getTermByUuid(uuidSuperfamily);
276 }
277 public static final Rank FAMILY(){
278 return getTermByUuid(uuidFamily);
279 }
280 public static final Rank SUBFAMILY(){
281 return getTermByUuid(uuidSubfamily);
282 }
283 public static final Rank INFRAFAMILY(){
284 return getTermByUuid(uuidInfrafamily);
285 }
286 public static final Rank SUPERTRIBE(){
287 return getTermByUuid(uuidSupertribe);
288 }
289 public static final Rank TRIBE(){
290 return getTermByUuid(uuidTribe);
291 }
292 public static final Rank SUBTRIBE(){
293 return getTermByUuid(uuidSubtribe);
294 }
295 public static final Rank INFRATRIBE(){
296 return getTermByUuid(uuidInfratribe);
297 }
298 public static final Rank SUPRAGENERICTAXON(){
299 return getTermByUuid(uuidSupragenericTaxon);
300 }
301 public static final Rank GENUS(){
302 return getTermByUuid(uuidGenus);
303 }
304 public static final Rank SUBGENUS(){
305 return getTermByUuid(uuidSubgenus);
306 }
307 public static final Rank INFRAGENUS(){
308 return getTermByUuid(uuidInfragenus);
309 }
310 public static final Rank SECTION_BOTANY(){
311 return getTermByUuid(uuidSectionBotany);
312 }
313 public static final Rank SUBSECTION_BOTANY(){
314 return getTermByUuid(uuidSubsectionBotany);
315 }
316 public static final Rank SECTION_ZOOLOGY(){
317 return getTermByUuid(uuidSectionZoology);
318 }
319 public static final Rank SUBSECTION_ZOOLOGY(){
320 return getTermByUuid(uuidSubsectionZoology);
321 }
322 public static final Rank SERIES(){
323 return getTermByUuid(uuidSeries);
324 }
325 public static final Rank SUBSERIES(){
326 return getTermByUuid(uuidSubseries);
327 }
328 public static final Rank SPECIESAGGREGATE(){
329 return getTermByUuid(uuidSpeciesAggregate);
330 }
331 public static final Rank SPECIESGROUP(){
332 return getTermByUuid(uuidSpeciesGroup);
333 }
334 /**
335 * 'Unranked infrageneric'. An infrageneric rank which is on purpose not further defined.
336 * This sometimes holds for names from the 19th century.
337 */
338 public static final Rank INFRAGENERICTAXON(){
339 return getTermByUuid(uuidInfragenericTaxon);
340 }
341 public static final Rank SPECIES(){
342 return getTermByUuid(uuidSpecies);
343 }
344 public static final Rank SUBSPECIFICAGGREGATE(){
345 return getTermByUuid(uuidSubspecificAggregate);
346 }
347 public static final Rank SUBSPECIES(){
348 return getTermByUuid(uuidSubspecies);
349 }
350 public static final Rank INFRASPECIES(){
351 return getTermByUuid(uuidInfraspecies);
352 }
353 public static final Rank VARIETY(){
354 return getTermByUuid(uuidVariety);
355 }
356 public static final Rank BIOVARIETY(){
357 return getTermByUuid(uuidBioVariety);
358 }
359 public static final Rank PATHOVARIETY(){
360 return getTermByUuid(uuidPathoVariety);
361 }
362 public static final Rank SUBVARIETY(){
363 return getTermByUuid(uuidSubvariety);
364 }
365 public static final Rank SUBSUBVARIETY(){
366 return getTermByUuid(uuidSubsubvariety );
367 }
368 public static final Rank CONVAR(){
369 return getTermByUuid(uuidConvar);
370 }
371 public static final Rank FORM(){
372 return getTermByUuid(uuidForm);
373 }
374 public static final Rank SPECIALFORM(){
375 return getTermByUuid(uuidSpecialForm);
376 }
377 public static final Rank SUBFORM(){
378 return getTermByUuid(uuidSubform);
379 }
380 public static final Rank SUBSUBFORM(){
381 return getTermByUuid(uuidSubsubform);
382 }
383 /**
384 * 'Unranked infraspecific'. An infraspecific rank which is on purpose not further defined.
385 * This sometimes holds for names from the 19th century.
386 */
387 public static final Rank INFRASPECIFICTAXON(){
388 return getTermByUuid(uuidInfraspecificTaxon);
389 }
390 public static final Rank CANDIDATE(){
391 return getTermByUuid(uuidCandidate);
392 }
393 public static final Rank DENOMINATIONCLASS(){
394 return getTermByUuid(uuidDenominationClass);
395 }
396 public static final Rank GREX(){
397 return getTermByUuid(uuidGrex);
398 }
399 public static final Rank GRAFTCHIMAERA(){
400 return getTermByUuid(uuidGraftChimaera);
401 }
402 public static final Rank CULTIVARGROUP(){
403 return getTermByUuid(uuidCultivarGroup);
404 }
405 public static final Rank CULTIVAR(){
406 return getTermByUuid(uuidCultivar);
407 }
408 public static final Rank UNKNOWN_RANK(){
409 return getTermByUuid(uuidUnknownRank);
410 }
411 public static final Rank NATIO(){
412 return getTermByUuid(uuidNatio);
413 }
414 /**
415 * @see #INFRASPECIFICTAXON()
416 */
417 public static final Rank UNRANKED_INFRASPECIFIC(){
418 return getTermByUuid(uuidInfraspecificTaxon);
419 }
420 /**
421 * @see #INFRAGENERICTAXON()
422 */
423 public static final Rank UNRANKED_INFRAGENERIC(){
424 return getTermByUuid(uuidInfragenericTaxon);
425 }
426
427 /**
428 * Returns the boolean value indicating whether <i>this</i> rank is higher than
429 * the genus rank (true) or not (false). Returns false if <i>this</i> rank is null.
430 *
431 * @see #isGenus()
432 * @see #isInfraGeneric()
433 * @see #isSpecies()
434 * @see #isInfraSpecific()
435 */
436 @Transient
437 public boolean isSupraGeneric(){
438 return (this.isHigher(Rank.GENUS()));
439 }
440
441 /**
442 * Returns the boolean value indicating whether <i>this</i> rank is the genus rank
443 * (true) or not (false). Returns false if <i>this</i> rank is null.
444 *
445 * @see #isSupraGeneric()
446 * @see #isInfraGeneric()
447 * @see #isSpecies()
448 * @see #isInfraSpecific()
449 */
450 @Transient
451 public boolean isGenus(){
452 return (this.equals(Rank.GENUS()));
453 }
454
455 /**
456 * Returns the boolean value indicating whether <i>this</i> rank is higher than the
457 * species rank and lower than the genus rank (true) or not (false). Species groups or
458 * aggregates are also handled as infrageneric ranks.
459 * Returns false if <i>this</i> rank is null.
460 *
461 * @see #isSupraGeneric()
462 * @see #isGenus()
463 * @see #isSpeciesAggregate()
464 * @see #isSpecies()
465 * @see #isInfraSpecific()
466 */
467 @Transient
468 public boolean isInfraGeneric(){
469 return (this.isLower(Rank.GENUS()) && this.isHigher(Rank.SPECIES()));
470 }
471
472 /**
473 * Returns true if this rank indicates a rank that aggregates species
474 * like species aggregates or species groups, false otherwise. This methods
475 * currently returns false for all user defined ranks.
476 * @return
477 */
478 @Transient
479 public boolean isSpeciesAggregate(){
480 return (this.equals(Rank.SPECIESAGGREGATE()) || (this.isLower(Rank.SPECIESAGGREGATE()) && this.isHigher(Rank.SPECIES())));
481 }
482
483 /**
484 * Returns the boolean value indicating whether <i>this</i> rank is the species
485 * rank (true) or not (false). Returns false if <i>this</i> rank is null.
486 *
487 * @see #isSupraGeneric()
488 * @see #isGenus()
489 * @see #isInfraGeneric()
490 * @see #isInfraSpecific()
491 */
492 @Transient
493 public boolean isSpecies(){
494 return (this.equals(Rank.SPECIES()));
495 }
496
497 /**
498 * Returns the boolean value indicating whether <i>this</i> rank is lower than the
499 * species rank (true) or not (false). Returns false if <i>this</i> rank is null.
500 *
501 * @see #isSupraGeneric()
502 * @see #isGenus()
503 * @see #isInfraGeneric()
504 * @see #isSpecies()
505 */
506 @Transient
507 public boolean isInfraSpecific(){
508 return (this.isLower(Rank.SPECIES()));
509 }
510
511
512 /**
513 * Returns the rank identified through a name (abbreviated or not).
514 * Preliminary implementation for BotanicalNameParser.
515 *
516 * @param strRank the string identifying the rank
517 * @return the rank
518 */
519 public static Rank getRankByNameOrAbbreviation(String strRank)
520 throws UnknownCdmTypeException{
521 return getRankByNameOrAbbreviation(strRank, false);
522 }
523
524 /**
525 * Returns the rank identified through a name (abbreviated or not) for a given nomenclatural code.
526 * Preliminary implementation for BotanicalNameParser.
527 *
528 * @param strRank the string identifying the rank
529 * @param nc the nomenclatural code
530 * @return the rank
531 */
532 public static Rank getRankByNameOrAbbreviation(String strRank, NomenclaturalCode nc)
533 throws UnknownCdmTypeException{
534 return getRankByNameOrAbbreviation(strRank, nc, false);
535 }
536
537 // TODO
538 // Preliminary implementation for BotanicalNameParser.
539 // not yet complete
540 /**
541 * Returns the rank identified through a name (abbreviated or not).
542 * Preliminary implementation for BotanicalNameParser.
543 *
544 * @param strRank the string identifying the rank
545 * @param useUnknown if true the rank UNKNOWN_RANK is returned if the abbrev is
546 * unknown or not yet implemented
547 * @return the rank
548 */
549 public static Rank getRankByNameOrAbbreviation(String strRank, boolean useUnknown)
550 throws UnknownCdmTypeException{
551 try {
552 return getRankByAbbreviation(strRank);
553 } catch (UnknownCdmTypeException e) {
554 return getRankByName(strRank, useUnknown);
555 }
556 }
557
558 // TODO
559 // Preliminary implementation for BotanicalNameParser.
560 // not yet complete
561 /**
562 * Returns the rank identified through a name (abbreviated or not).
563 * Preliminary implementation for BotanicalNameParser.
564 *
565 * @param strRank the string identifying the rank
566 * @param nc the nomenclatural code
567 * @param useUnknown if true the rank UNKNOWN_RANK is returned if the abbrev is
568 * unknown or not yet implemented
569 * @return the rank
570 */
571 public static Rank getRankByNameOrAbbreviation(String strRank, NomenclaturalCode nc, boolean useUnknown)
572 throws UnknownCdmTypeException{
573 try {
574 return getRankByAbbreviation(strRank, nc);
575 } catch (UnknownCdmTypeException e) {
576 return getRankByName(strRank, nc, useUnknown);
577 }
578 }
579
580 /**
581 * Returns the rank identified through an abbreviated name.
582 * Preliminary implementation for BotanicalNameParser.<BR>
583 * Note: For abbrev = "[unranked]" the result is undefined.
584 * It maybe the infrageneric unranked or the infraspecific unranked.
585 * You need to define by context which one is correct.
586 *
587 * @param abbrev the string for the name abbreviation
588 * @return the rank
589 */
590 public static Rank getRankByAbbreviation(String abbrev)
591 throws UnknownCdmTypeException{
592 return getRankByAbbreviation(abbrev, false);
593 }
594
595 /**
596 * Returns the rank identified through an abbreviated name for a given nomenclatural code.
597 * See also {@link #getRankByAbbreviation(String, boolean)}
598 *
599 * @param abbrev the string for the name abbreviation
600 * @param nc the nomenclatural code
601 * @return the rank
602 */
603 public static Rank getRankByAbbreviation(String abbrev, NomenclaturalCode nc) throws UnknownCdmTypeException{
604 return getRankByAbbreviation(abbrev, nc, false);
605 }
606
607 // TODO
608 // Preliminary implementation for BotanicalNameParser.
609 // not yet complete
610 /**
611 * Returns the rank identified through an abbreviated representation.
612 * At the moment it uses the English abbreviations (being Latin because
613 * we do not have Latin representations yet.
614 * TODO
615 * If no according abbreviation is available it throws either an UnknownCdmTypeException
616 * or an #Rank.UNKNOWN() object depending on the useUnknown flag.
617 *
618 * @param abbrev the string for the name abbreviation
619 * @param useUnknown if true the rank UNKNOWN_RANK is returned if the abbrev is
620 * unknown or not yet existent
621 * @return the rank
622 */
623 public static Rank getRankByAbbreviation(String abbrev, boolean useUnknown) throws UnknownCdmTypeException{
624 Rank result = null;
625 if (abbrev == null){
626 throw new NullPointerException("Abbrev is NULL in getRankByAbbreviation");
627 }
628 if (abbrev.trim().equals("")){
629 //handle empty abbrev as unknown
630 abbrev = "oijaämöö";
631 }
632 if (abbrevMap == null){
633 return null;
634 }
635 UUID uuid = abbrevMap.get(abbrev);
636 if (uuid != null ){
637 result = getTermByUuid(uuid);
638 }
639 if (result != null){
640 return result;
641 }else {
642 if (abbrev == null){
643 abbrev = "(null)";
644 }
645 if (useUnknown){
646 logger.info("Unknown rank name: " + abbrev + ". Rank 'UNKNOWN_RANK' created instead");
647 return Rank.UNKNOWN_RANK();
648 }else{
649 throw new UnknownCdmTypeException("Unknown rank abbreviation: " + abbrev);
650 }
651 }
652 }
653
654 // TODO
655 // Preliminary implementation to cover Botany and Zoology.
656 /**
657 * Returns the rank identified through an abbreviated name for a given nomenclatural code.
658 * Preliminary implementation for ICBN and ICZN.
659 * See also {@link #getRankByAbbreviation(String, boolean)}
660
661 *
662 * @param abbrev the string for the name abbreviation
663 * @param nc the nomenclatural code
664 * @param useUnknown if true the rank UNKNOWN_RANK is returned if the abbrev is
665 * unknown or not yet implemented
666 * @return the rank
667 */
668 public static Rank getRankByAbbreviation(String abbrev, NomenclaturalCode nc, boolean useUnknown)
669 throws UnknownCdmTypeException{
670
671 if (nc != null && nc.equals(NomenclaturalCode.ICZN)) {
672 if (abbrev.equalsIgnoreCase("sect.")) { return Rank.SECTION_ZOOLOGY();
673 } else if (abbrev.equalsIgnoreCase("subsect.")) { return Rank.SUBSECTION_ZOOLOGY();
674 }
675 }
676 return getRankByAbbreviation(abbrev, useUnknown);
677 }
678
679 // TODO
680 // Preliminary implementation for BotanicalNameParser.
681 // not yet complete
682 /**
683 * Returns the rank identified through a name.
684 * Preliminary implementation for BotanicalNameParser.
685 *
686 * @param rankName the string for the name of the rank
687 * @return the rank
688 */
689 public static Rank getRankByName(String rankName) throws UnknownCdmTypeException{
690 return getRankByName(rankName, false);
691 }
692
693
694 // TODO
695 // Preliminary implementation for ICBN and ICZN.
696 // not yet complete
697 /**
698 * Returns the rank identified through a name for a given nomenclatural code.
699 * Preliminary implementation for ICBN and ICZN.
700 *
701 * @param rankName the string for the name of the rank
702 * @param nc the nomenclatural code
703 * @return the rank
704 */
705 public static Rank getRankByName(String rankName, NomenclaturalCode nc) throws UnknownCdmTypeException{
706 return getRankByName(rankName, nc, false);
707 }
708
709 /**
710 * Returns the rank identified through a name.
711 * Preliminary implementation for BotanicalNameParser.
712 * TODO At the moment we do not have Latin representations yet.
713 *
714 * @param rankName the string for the name of the rank
715 * @param useUnknown if true the rank UNKNOWN_RANK is returned if the rank name is
716 * unknown or not yet implemented
717 * @return the rank
718 */
719 public static Rank getRankByName(String rankName, boolean useUnknown)
720 throws UnknownCdmTypeException{
721 if (rankName.equalsIgnoreCase("Regnum")){ return Rank.KINGDOM();
722 }else if (rankName.equalsIgnoreCase("Subregnum")){ return Rank.SUBKINGDOM();
723 }else if (rankName.equalsIgnoreCase("Phylum")){ return Rank.PHYLUM();
724 }else if (rankName.equalsIgnoreCase("Subphylum")){ return Rank.SUBPHYLUM();
725 }else if (rankName.equalsIgnoreCase("Divisio")){ return Rank.DIVISION();
726 }else if (rankName.equalsIgnoreCase("Subdivisio")){ return Rank.SUBDIVISION();
727 }else if (rankName.equalsIgnoreCase("Classis")){ return Rank.CLASS();
728 }else if (rankName.equalsIgnoreCase("Subclassis")){ return Rank.SUBCLASS();
729 }else if (rankName.equalsIgnoreCase("Superordo")){ return Rank.SUPERORDER();
730 }else if (rankName.equalsIgnoreCase("Ordo")){ return Rank.ORDER();
731 }else if (rankName.equalsIgnoreCase("Subordo")){ return Rank.SUBORDER();
732 }else if (rankName.equalsIgnoreCase("Familia")){ return Rank.FAMILY();
733 }else if (rankName.equalsIgnoreCase("Subfamilia")){ return Rank.SUBFAMILY();
734 }else if (rankName.equalsIgnoreCase("Tribus")){ return Rank.TRIBE();
735 }else if (rankName.equalsIgnoreCase("Subtribus")){ return Rank.SUBTRIBE();
736 }else if (rankName.equalsIgnoreCase("Genus")){ return Rank.GENUS();
737 }else if (rankName.equalsIgnoreCase("Subgenus")){ return Rank.SUBGENUS();
738 }else if (rankName.equalsIgnoreCase("Sectio")){ return Rank.SECTION_BOTANY();
739 }else if (rankName.equalsIgnoreCase("Subsectio")){ return Rank.SUBSECTION_BOTANY();
740 }else if (rankName.equalsIgnoreCase("Series")){ return Rank.SERIES();
741 }else if (rankName.equalsIgnoreCase("Subseries")){ return Rank.SUBSERIES();
742 }else if (rankName.equalsIgnoreCase("Aggregate")){ return Rank.SPECIESAGGREGATE();
743 }else if (rankName.equalsIgnoreCase("Speciesgroup")){ return Rank.SPECIESGROUP();
744 }else if (rankName.equalsIgnoreCase("Species")){ return Rank.SPECIES();
745 }else if (rankName.equalsIgnoreCase("Subspecies")){ return Rank.SUBSPECIES();
746 }else if (rankName.equalsIgnoreCase("Convarietas")){ return Rank.CONVAR();
747 }else if (rankName.equalsIgnoreCase("Varietas")){ return Rank.VARIETY();
748 }else if (rankName.equalsIgnoreCase("Subvarietas")){ return Rank.SUBVARIETY();
749 }else if (rankName.equalsIgnoreCase("Forma")){ return Rank.FORM();
750 }else if (rankName.equalsIgnoreCase("Subforma")){ return Rank.SUBFORM();
751 }else if (rankName.equalsIgnoreCase("Forma spec.")){ return Rank.SPECIALFORM();
752 }else if (rankName.equalsIgnoreCase("tax.infragen.")){ return Rank.INFRAGENERICTAXON();
753 }else if (rankName.equalsIgnoreCase("tax.infrasp.")){ return Rank.INFRASPECIFICTAXON();
754 // old ranks
755 }else if (rankName.equalsIgnoreCase("proles")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
756 }else if (rankName.equalsIgnoreCase("race")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
757 }else if (rankName.equalsIgnoreCase("taxon")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
758 }else if (rankName.equalsIgnoreCase("sublusus")){ return Rank.INFRASPECIFICTAXON(); //to create the name put prol. and the infraspeciesepi to the field unnamed namephrase
759
760 }else{
761 if (rankName == null){
762 rankName = "(null)"; //see NPE above
763 }
764 if (useUnknown){
765 logger.info("Unknown rank name: " + rankName+". Rank 'UNKNOWN_RANK' created instead");
766 return Rank.UNKNOWN_RANK();
767 }else{
768 throw new UnknownCdmTypeException("Unknown rank name: " + rankName);
769 }
770 }
771 }
772
773 /**
774 * Defines the rank according to the English name.
775 * @param rankName English rank name.
776 * @param nc Defines the handling of the section and subsection ranks. These are in different orders depending on the
777 * nomenclatural code.
778 * @param useUnknown if true, the "Unknown" rank is returned as a placeholder.
779 * @return
780 * @throws UnknownCdmTypeException never thrown if useUnknown is true
781 */
782 public static Rank getRankByEnglishName(String rankName, NomenclaturalCode nc, boolean useUnknown) throws UnknownCdmTypeException{
783 Rank result = null;
784 if (rankName == null){
785 throw new NullPointerException("Abbrev is NULL in getRankByAbbreviation");
786 }
787 if (labelMap == null){
788 return null;
789 }
790 //handle section and subsection (not unique representations)
791 if (rankName.equalsIgnoreCase("Section")){
792 if (nc != null && nc.equals(NomenclaturalCode.ICZN)){ return Rank.SECTION_ZOOLOGY();
793 }else if (nc != null && nc.equals(NomenclaturalCode.ICBN)){return Rank.SECTION_BOTANY();
794 }else{
795 String errorWarning = "Section is only defined for ICZN and ICBN at the moment but here needed for " + ((nc == null)? "(null)": nc.toString());
796 logger.warn(errorWarning);
797 throw new UnknownCdmTypeException (errorWarning);
798 }
799 }else if (rankName.equalsIgnoreCase("Subsection")){
800 if (nc != null && nc.equals(NomenclaturalCode.ICZN)){ return Rank.SECTION_ZOOLOGY();
801 }else if (nc != null && nc.equals(NomenclaturalCode.ICBN)){ return Rank.SECTION_BOTANY();
802 }else{
803 String errorWarning = "Subsection is only defined for ICZN and ICBN at the moment but here needed for " + ((nc == null)? "(null)": nc.toString());
804 logger.warn(errorWarning);
805 throw new UnknownCdmTypeException (errorWarning);
806 }
807 }
808
809 rankName = rankName.toLowerCase();
810
811 UUID uuid = labelMap.get(rankName);
812 if (uuid != null ){
813 result = getTermByUuid(uuid);
814 }
815 if (result != null){
816 return result;
817 }else {
818 if (rankName == null){
819 rankName = "(null)";
820 }
821 if (useUnknown){
822 logger.info("Unknown rank name: " + rankName + ". Rank 'UNKNOWN_RANK' created instead");
823 return Rank.UNKNOWN_RANK();
824 }else{
825 throw new UnknownCdmTypeException("Unknown rank: " + rankName);
826 }
827 }
828 }
829
830
831 public static Rank getRankByName(String rankName, NomenclaturalCode nc, boolean useUnknown)
832 throws UnknownCdmTypeException {
833
834 if (nc.equals(NomenclaturalCode.ICZN)) {
835 if (rankName.equalsIgnoreCase("Sectio")) { return Rank.SECTION_ZOOLOGY();
836 }else if (rankName.equalsIgnoreCase("Subsectio")) { return Rank.SUBSECTION_ZOOLOGY();
837 }
838 }
839 return getRankByName(rankName, useUnknown);
840 }
841
842 /**
843 * Returns the abbreviated rank name for <i>this</i> rank according to the English representation
844 * abbreviated label.
845 * TODO Needs to be changed to Latin as soon as Latin representations are available.
846 *
847 * @return the abbreviation string for <i>this</i> rank
848 */
849 public String getAbbreviation(){
850 Language language = Language.ENGLISH();
851 String result = this.getRepresentation(language).getAbbreviatedLabel();
852 if (result== null) {
853 logger.warn("Abbreviation for this Rank " + this.toString() + " not yet implemented");
854 return "no abbreviation available.";
855 }else{
856 return result;
857 }
858 }
859 @Transient
860 public String getInfraGenericMarker() throws UnknownCdmTypeException{
861 String result = null;
862 if (! this.isInfraGeneric()){
863 throw new IllegalStateException("An infrageneric marker is only available for a infrageneric rank but was asked for rank: " + this.toString());
864 }else{
865 result = this.getAbbreviation();
866 }
867 if (result == null){
868 throw new UnknownCdmTypeException("Abbreviation for rank unknown: " + this.toString());
869 }
870 return result;
871 }
872
873
874
875 @Override
876 public Rank readCsvLine(Class<Rank> termClass, List<String> csvLine, Map<UUID, DefinedTermBase> terms) {
877 return super.readCsvLine(termClass, csvLine, terms);
878 }
879
880 @Override
881 protected void setDefaultTerms(TermVocabulary<Rank> termVocabulary) {
882 termMap = new HashMap<UUID, Rank>();
883 for (Rank term : termVocabulary.getTerms()){
884 termMap.put(term.getUuid(), (Rank)term);
885 addRank(term);
886 }
887 }
888
889 /**
890 * @param term
891 */
892 private void addRank(Rank rank) {
893 if (rank == null){
894 logger.warn("rank is NULL");
895 return;
896 }
897 if (rank.getUuid().equals(uuidSectionZoology) || rank.getUuid().equals(uuidSubsectionZoology )){
898 //sect./subsect. is used for botanical sections, see also #getRankByAbbreviation(String, NomenclaturalCode, boolean)
899 return;
900 }
901 Language lang = Language.DEFAULT(); //TODO should be Latin but at the moment we have only English representations
902 Representation representation = rank.getRepresentation(lang);
903 String abbrevLabel = representation.getAbbreviatedLabel();
904 String label = representation.getLabel();
905 if (abbrevLabel == null){
906 logger.warn("Abbreviated lable for rank is NULL.Can't add rank: " + CdmUtils.Nz(rank.getLabel()));
907 return;
908 }
909 //initialize maps
910 if (abbrevMap == null){
911 abbrevMap = new HashMap<String, UUID>();
912 }
913 if (labelMap == null){
914 labelMap = new HashMap<String, UUID>();
915 }
916 //add to map
917 abbrevMap.put(abbrevLabel, rank.getUuid());
918 labelMap.put(label.toLowerCase(), rank.getUuid());
919 }
920
921
922 /**
923 * It is nessecary to skip the vocabulary check, otherwise we would have
924 * problems in some CacheStrategies, due to uninitialized Vocabularies.
925 *
926 * @see eu.etaxonomy.cdm.model.common.OrderedTermBase#compareTo(eu.etaxonomy.cdm.model.common.OrderedTermBase)
927 */
928 @Override
929 public int compareTo(Rank orderedTerm) {
930 return performCompareTo(orderedTerm, true);
931 }
932
933 }