(no commit message)
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / TaxonNameBase.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 eu.etaxonomy.cdm.model.occurrence.Specimen;
13 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
14 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
15 import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
16 import eu.etaxonomy.cdm.model.taxon.Synonym;
17 import eu.etaxonomy.cdm.model.taxon.Taxon;
18 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
19 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
20 import eu.etaxonomy.cdm.model.common.IParsable;
21 import eu.etaxonomy.cdm.model.common.IRelated;
22 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
23 import eu.etaxonomy.cdm.model.common.IReferencedEntity;
24 import eu.etaxonomy.cdm.model.common.RelationshipBase;
25
26
27 import org.apache.log4j.Logger;
28 import org.hibernate.annotations.Cascade;
29 import org.hibernate.annotations.CascadeType;
30 import org.hibernate.collection.PersistentSet;
31
32 import eu.etaxonomy.cdm.strategy.cache.INameCacheStrategy;
33
34
35 import java.lang.reflect.Method;
36 import java.util.*;
37
38 import javax.persistence.*;
39
40 /**
41 * The upmost (abstract) class for scientific taxon names regardless of any
42 * particular nomenclatural code. The scientific name including author strings and
43 * maybe year can be stored as a string in the inherited {@link common.IdentifiableEntity#getTitleCache() titleCache} attribute.
44 * The scientific name string without author strings and year can be stored in the {@link #getNameCache() nameCache} attribute.
45 * The scientific taxon name does not depend on the use made of it
46 * in a publication or a treatment ({@link taxon.TaxonBase taxon concept respectively potential taxon})
47 * as an "accepted" respectively "correct" name ({@link taxon.Taxon taxon})
48 * or as a {@link taxon.Synonym synonym}.
49 *
50 * @author m.doering
51 * @version 1.0
52 * @created 08-Nov-2007 13:06:57
53 */
54 @Entity
55 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
56 public abstract class TaxonNameBase<T extends TaxonNameBase> extends IdentifiableEntity<TaxonNameBase> implements IReferencedEntity, IParsable, IRelated<NameRelationship> {
57 static Logger logger = Logger.getLogger(TaxonNameBase.class);
58 //The scientific name without author strings and year
59 private String nameCache;
60 //Non-atomised addition to a name not ruled by a nomenclatural code
61 private String appendedPhrase;
62 //Details of the nomenclatural reference (protologue). These are mostly (implicitly) pages but can also be figures or
63 //tables or any other element of a publication. {only if a nomenclatural reference exists}
64 private String nomenclaturalMicroReference;
65 //this flag will be set to true if the parseName method was unable to successfully parse the name
66 private boolean hasProblem = false;
67 protected Set<NameTypeDesignation> nameTypeDesignations = new HashSet<NameTypeDesignation>();
68 private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
69 private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
70 private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
71 private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
72 private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
73 private Rank rank;
74 //if set, the Reference.isNomenclaturallyRelevant flag should be set to true!
75 private INomenclaturalReference nomenclaturalReference;
76
77 //this flag shows if the getNameCache should return generated value(false) or the given String(true)
78 protected boolean protectedNameCache;
79
80 protected INameCacheStrategy<T> cacheStrategy;
81 static Method methodTaxonBaseSetName;
82
83 // ************* CONSTRUCTORS *************/
84 /**
85 * Class constructor: creates a new empty taxon name instance.
86 *
87 * @see #TaxonNameBase(Rank)
88 * @see #TaxonNameBase(HomotypicalGroup)
89 * @see #TaxonNameBase(Rank, HomotypicalGroup)
90 */
91 public TaxonNameBase() {
92 this(null, null);
93 }
94 /**
95 * Class constructor: creates a new taxon name instance
96 * only containing its {@link common.Rank rank}.
97 *
98 * @param rank the rank to be assigned to this taxon name
99 * @see #TaxonNameBase()
100 * @see #TaxonNameBase(HomotypicalGroup)
101 * @see #TaxonNameBase(Rank, HomotypicalGroup)
102 */
103 public TaxonNameBase(Rank rank) {
104 this(rank, null);
105 }
106 /**
107 * Class constructor: creates a new taxon name instance
108 * only containing its {@link common.HomotypicalGroup homotypical group}.
109 * The new taxon name instance will be also added to the set of taxon names
110 * belonging to this homotypical group. If the homotypical group
111 * does not exist a new instance will be created for it.
112 *
113 * @param homotypicalGroup the homotypical group to which this taxon name belongs
114 * @see #TaxonNameBase()
115 * @see #TaxonNameBase(Rank)
116 * @see #TaxonNameBase(Rank, HomotypicalGroup)
117 */
118 public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
119 this(null, homotypicalGroup);
120 }
121 /**
122 * Class constructor: creates a new instance of a taxon name
123 * only containing its {@link common.Rank rank} and
124 * its {@link common.HomotypicalGroup homotypical group}.
125 *
126 * @param rank the rank to be assigned to this taxon name
127 * @param homotypicalGroup the homotypical group to which this taxon name belongs
128 * @see #TaxonNameBase()
129 * @see #TaxonNameBase(Rank)
130 * @see #TaxonNameBase(HomotypicalGroup)
131 */
132 public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
133 super();
134 this.setRank(rank);
135 if (homotypicalGroup == null){
136 homotypicalGroup = new HomotypicalGroup();
137 }
138 homotypicalGroup.addTypifiedName(this);
139 }
140
141 //********* METHODS **************************************/
142
143
144
145 /**
146 * Generates the composed name string of this taxon name without authors
147 * or year according to the strategy defined in
148 * {@link eu.etaxonomy.cdm.strategy.cache.INameCacheStrategy INameCacheStrategy}.
149 * The result might be stored in {@link #getNameCache() nameCache} if the
150 * flag {@link #isProtectedNameCache() protectedNameCache} is not set.
151 *
152 * @return the string with the composed name of this taxon name without authors or year
153 */
154 protected String generateNameCache(){
155 if (cacheStrategy == null){
156 logger.warn("No CacheStrategy defined for taxonName: " + this.toString());
157 return null;
158 }else{
159 return cacheStrategy.getNameCache((T)this);
160 }
161 }
162
163 /**
164 * Returns or generates the nameCache (scientific name
165 * without author strings and year) string for this taxon name. If the
166 * {@link #isProtectedNameCache() protectedNameCache} flag is not set (False)
167 * the string will be generated according to a defined strategy,
168 * otherwise the value of the actual nameCache string will be returned.
169 *
170 * @return the string which identifies this taxon name (without authors or year)
171 * @see #generateNameCache()
172 */
173 public String getNameCache() {
174 if (protectedNameCache){
175 return this.nameCache;
176 }
177 // is title dirty, i.e. equal NULL?
178 if (nameCache == null){
179 this.nameCache = generateNameCache();
180 }
181 return nameCache;
182 }
183
184 /**
185 * Assigns a nameCache string to this taxon name and protects it from being overwritten.
186 *
187 * @param nameCache the string which identifies this taxon name (without authors or year)
188 * @see #getNameCache()
189 */
190 public void setNameCache(String nameCache){
191 this.nameCache = nameCache;
192 this.setProtectedTitleCache(false);
193 this.setProtectedNameCache(true);
194 }
195
196 /**
197 * Returns the boolean value of the flag intended to protect (true)
198 * or not (false) the {@link #getNameCache() nameCache} (scientific name without author strings and year)
199 * string of this taxon name.
200 *
201 * @return the boolean value of the protectedNameCache flag
202 * @see #getNameCache()
203 */
204 public boolean isProtectedNameCache() {
205 return protectedNameCache;
206 }
207
208 /**
209 * @see #isProtectedNameCache()
210 */
211 public void setProtectedNameCache(boolean protectedNameCache) {
212 this.protectedNameCache = protectedNameCache;
213 }
214
215 /**
216 * Returns the boolean value "true" if the components of this taxon name
217 * follow the rules of the corresponding {@link NomenclaturalCode nomenclatural code},
218 * "false" otherwise. The nomenclatural code depends on
219 * the concrete name subclass ({@link BacterialName BacterialName},
220 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
221 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName})
222 * to which this taxon name belongs.
223 *
224 * @return the boolean value expressing the compliance of this taxon name to the nomenclatural code
225 */
226 @Transient
227 public abstract boolean isCodeCompliant();
228
229
230 /**
231 * Returns the set of all {@link NameRelationship name relationships}
232 * in which this taxon name is involved. A taxon name can be both source
233 * in some name relationships or target in some others.
234 *
235 * @see #getRelationsToThisName()
236 * @see #getRelationsFromThisName()
237 * @see #addNameRelationship(NameRelationship)
238 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
239 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
240 */
241 @Transient
242 public Set<NameRelationship> getNameRelations() {
243 Set<NameRelationship> rels = new HashSet<NameRelationship>();
244 rels.addAll(getRelationsFromThisName());
245 rels.addAll(getRelationsToThisName());
246 return rels;
247 }
248 /**
249 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from this taxon name to another taxon name
250 * and adds it both to the set of {@link #getRelationsFromThisName() relations from this taxon name} and
251 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
252 *
253 * @param toName the taxon name of the target for this new name relationship
254 * @param type the type of this new name relationship
255 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
256 * @see #getRelationsToThisName()
257 * @see #getNameRelations()
258 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
259 * @see #addNameRelationship(NameRelationship)
260 */
261 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
262 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
263 }
264 /**
265 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to this taxon name
266 * and adds it both to the set of {@link #getRelationsToThisName() relations to this taxon name} and
267 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
268 *
269 * @param fromName the taxon name of the source for this new name relationship
270 * @param type the type of this new name relationship
271 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
272 * @see #getRelationsFromThisName()
273 * @see #getNameRelations()
274 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
275 * @see #addNameRelationship(NameRelationship)
276 */
277 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
278 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
279 }
280 /**
281 * Adds an existing {@link NameRelationship name relationship} either to the set of
282 * {@link #getRelationsToThisName() relations to this taxon name} or to the set of
283 * {@link #getRelationsFromThisName() relations from this taxon name}. If neither the
284 * source nor the target of the name relationship match with this taxon
285 * no addition will be carried out.
286 *
287 * @param rel the name relationship to be added to one of this taxon name's name relationships sets
288 * @see #getNameRelations()
289 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
290 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
291 */
292 protected void addNameRelationship(NameRelationship rel) {
293 if (rel!=null && rel.getToName().equals(this)){
294 this.relationsToThisName.add(rel);
295 }else if(rel!=null && rel.getFromName().equals(this)){
296 this.relationsFromThisName.add(rel);
297 }else{
298 //TODO: raise error???
299 }
300 }
301 /**
302 * Removes one {@link NameRelationship name relationship} from one of both sets of
303 * {@link #getNameRelations() name relationships} in which this taxon name is involved.
304 * The name relationship will also be removed from one of both sets belonging
305 * to the second taxon name involved. Furthermore the fromName and toName
306 * attributes of the name relationship object will be nullified.
307 *
308 * @param nameRelation the name relationship which should be deleted from one of both sets
309 * @see #getNameRelations()
310 */
311 public void removeNameRelationship(NameRelationship nameRelation) {
312 //TODO to be implemented?
313 logger.warn("not yet fully implemented?");
314 this.relationsToThisName.remove(nameRelation);
315 this.relationsFromThisName.remove(nameRelation);
316 }
317
318
319 public void addRelationship(NameRelationship relation) {
320 addNameRelationship(relation);
321 }
322
323
324 /**
325 * Returns the set of all {@link NameRelationship name relationships}
326 * in which this taxon name is involved as a source.
327 *
328 * @see #getNameRelations()
329 * @see #getRelationsToThisName()
330 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
331 */
332 @OneToMany(mappedBy="fromName", fetch= FetchType.EAGER)
333 @Cascade({CascadeType.SAVE_UPDATE})
334 public Set<NameRelationship> getRelationsFromThisName() {
335 return relationsFromThisName;
336 }
337 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
338 this.relationsFromThisName = relationsFromThisName;
339 }
340
341 /**
342 * Returns the set of all {@link NameRelationship name relationships}
343 * in which this taxon name is involved as a target.
344 *
345 * @see #getNameRelations()
346 * @see #getRelationsFromThisName()
347 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
348 */
349 @OneToMany(mappedBy="toName", fetch= FetchType.EAGER)
350 @Cascade({CascadeType.SAVE_UPDATE})
351 public Set<NameRelationship> getRelationsToThisName() {
352 return relationsToThisName;
353 }
354 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
355 this.relationsToThisName = relationsToThisName;
356 }
357
358
359 /**
360 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
361 * to this taxon name according to its corresponding nomenclature code.
362 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
363 * and the nomenclatural code rule considered.
364 *
365 * @see NomenclaturalStatus
366 * @see NomenclaturalStatusType
367 */
368 @OneToMany(fetch= FetchType.EAGER)
369 @Cascade({CascadeType.SAVE_UPDATE})
370 public Set<NomenclaturalStatus> getStatus() {
371 return status;
372 }
373 /**
374 * @see #getStatus()
375 */
376 protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
377 this.status = nomStatus;
378 }
379 /**
380 * Adds a new {@link NomenclaturalStatus nomenclatural status}
381 * to this taxon name's set of nomenclatural status.
382 *
383 * @param nomStatus the nomenclatural status to be added
384 * @see #getStatus()
385 */
386 public void addStatus(NomenclaturalStatus nomStatus) {
387 this.status.add(nomStatus);
388 }
389 /**
390 * Removes one element from the set of nomenclatural status of this taxon name.
391 * Type and ruleConsidered attributes of the nomenclatural status object
392 * will be nullified.
393 *
394 * @param nomStatus the nomenclatural status of this taxon name which should be deleted
395 * @see #getStatus()
396 */
397 public void removeStatus(NomenclaturalStatus nomStatus) {
398 //TODO to be implemented?
399 logger.warn("not yet fully implemented?");
400 this.status.remove(nomStatus);
401 }
402
403
404 /**
405 * Indicates if this taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
406 * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
407 * of any other taxon name. Returns true, if a basionym or a replaced synonym
408 * relationship from this taxon name to another taxon name exists,
409 * false otherwise (also in case this taxon name is the only one in the
410 * homotypical group).
411 */
412 @Transient
413 public boolean isOriginalCombination(){
414 Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
415 for (NameRelationship relation : relationsFromThisName) {
416 if (relation.getType().equals(NameRelationshipType.BASIONYM()) ||
417 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM())) {
418 return true;
419 }
420 }
421 return false;
422 }
423
424 /**
425 * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
426 * The basionym of a taxon name is its epithet-bringing synonym.
427 * For instance Pinus abies L. was published by Linnaeus and the botanist
428 * Karsten transferred later this taxon to the genus Picea. Therefore,
429 * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
430 */
431 @Transient
432 public T getBasionym(){
433 //TODO: pick the right name relationships...
434 return null;
435 }
436 /**
437 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
438 * The basionym relationship will be added to this taxon name
439 * and to the basionym. The basionym cannot have itself a basionym.
440 *
441 * @see #getBasionym()
442 * @see #setBasionym(TaxonNameBase, String)
443 */
444 public void setBasionym(T basionym){
445 setBasionym(basionym, null);
446 }
447 /**
448 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name
449 * and keeps the nomenclatural rule considered for it. The basionym
450 * relationship will be added to this taxon name and to the basionym.
451 * The basionym cannot have itself a basionym.
452 *
453 * @see #getBasionym()
454 * @see #setBasionym(TaxonNameBase)
455 */
456 public void setBasionym(T basionym, String ruleConsidered){
457 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
458 }
459
460
461
462 //TODO for PROTOTYPE
463 @Transient
464 public INameCacheStrategy<T> getCacheStrategy() {
465 return cacheStrategy;
466 }
467 public void setCacheStrategy(INameCacheStrategy cacheStrategy) {
468 this.cacheStrategy = cacheStrategy;
469 }
470
471 @ManyToOne
472 //@Cascade({CascadeType.SAVE_UPDATE})
473 public Rank getRank(){
474 return this.rank;
475 }
476 public void setRank(Rank rank){
477 this.rank = rank;
478 }
479
480 @ManyToOne
481 @Cascade({CascadeType.SAVE_UPDATE})
482 public ReferenceBase getNomenclaturalReference(){
483 return (ReferenceBase) this.nomenclaturalReference;
484 }
485 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
486 this.nomenclaturalReference = nomenclaturalReference;
487 }
488
489
490 public String getAppendedPhrase(){
491 return this.appendedPhrase;
492 }
493 public void setAppendedPhrase(String appendedPhrase){
494 this.appendedPhrase = appendedPhrase;
495 }
496
497 public String getNomenclaturalMicroReference(){
498 return this.nomenclaturalMicroReference;
499 }
500 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
501 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
502 }
503
504 public boolean getHasProblem(){
505 return this.hasProblem;
506 }
507 public void setHasProblem(boolean hasProblem){
508 this.hasProblem = hasProblem;
509 }
510 /**
511 * Same as getHasProblem()
512 * @return
513 */
514 public boolean hasProblem(){
515 return getHasProblem();
516 }
517
518
519 @OneToMany
520 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
521 @Cascade(CascadeType.SAVE_UPDATE)
522 public Set<NameTypeDesignation> getNameTypeDesignations() {
523 return nameTypeDesignations;
524 }
525 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
526 this.nameTypeDesignations = nameTypeDesignations;
527 }
528
529 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
530 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
531 }
532 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
533 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
534 }
535 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
536 this.nameTypeDesignations.remove(typeDesignation);
537 }
538 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
539 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
540 }
541
542
543 @ManyToOne
544 @Cascade({CascadeType.SAVE_UPDATE})
545 public HomotypicalGroup getHomotypicalGroup() {
546 return homotypicalGroup;
547 }
548 @Deprecated //only for bidirectional and persistence use
549 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
550 this.homotypicalGroup = newHomotypicalGroup;
551 }
552
553 @Transient
554 public StrictReferenceBase getCitation(){
555 logger.warn("getCitation not yet implemented");
556 return null;
557 }
558
559 @Transient
560 public String getCitationString(){
561 logger.warn("getCitationString not yet implemented");
562 return null;
563 }
564
565 @Transient
566 public String[] getProblems(){
567 logger.warn("getProblems not yet implemented");
568 return null;
569 }
570
571 /**
572 * returns year of according nomenclatural reference, null if nomenclatural
573 * reference does not exist
574 */
575 @Transient
576 public String getReferenceYear(){
577 if (this.getNomenclaturalReference() != null ){
578 return this.getNomenclaturalReference().getYear();
579 }else{
580 return null;
581 }
582 }
583
584 @OneToMany(mappedBy="name", fetch= FetchType.EAGER)
585 public Set<TaxonBase> getTaxonBases() {
586 return this.taxonBases;
587 }
588 protected void setTaxonBases(Set<TaxonBase> taxonBases) {
589 if (taxonBases == null){
590 taxonBases = new HashSet<TaxonBase>();
591 }else{
592 this.taxonBases = taxonBases;
593 }
594 }
595 //TODO protected
596 public void addTaxonBase(TaxonBase taxonBase){
597 taxonBases.add(taxonBase);
598 initMethods();
599 invokeSetMethod(methodTaxonBaseSetName, taxonBase);
600 }
601
602 private void initMethods(){
603 if (methodTaxonBaseSetName == null){
604 try {
605 methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
606 methodTaxonBaseSetName.setAccessible(true);
607 } catch (Exception e) {
608 e.printStackTrace();
609 //TODO handle exception
610 }
611 }
612 }
613
614
615 /**
616 * Return a set of taxa that use this name.
617 * @return Set<Taxon> The set of taxa this TaxonName belongs to
618 */
619 @Transient
620 public Set<Taxon> getTaxa(){
621 Set<Taxon> result = new HashSet<Taxon>();
622 for (TaxonBase taxonBase : this.taxonBases){
623 if (taxonBase instanceof Taxon){
624 result.add((Taxon)taxonBase);
625 }
626 }
627 return result;
628 }
629
630 /**
631 * Return a set of synonyms that use this name
632 * @return The set of synonyms this TaxonName belongs to
633 */
634 @Transient
635 public Set<Synonym> getSynonyms() {
636 Set<Synonym> result = new HashSet<Synonym>();
637 for (TaxonBase taxonBase : this.taxonBases){
638 if (taxonBase instanceof Synonym){
639 result.add((Synonym)taxonBase);
640 }
641 }
642 return result;
643 }
644
645 @Transient
646 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
647 return this.getHomotypicalGroup().getTypeDesignations();
648 }
649
650 // Rank comparison shortcuts
651 @Transient
652 public boolean isSupraGeneric() {
653 return getRank().isSupraGeneric();
654 }
655 @Transient
656 public boolean isGenus() {
657 return getRank().isGenus();
658 }
659 @Transient
660 public boolean isInfraGeneric() {
661 return getRank().isInfraGeneric();
662 }
663 @Transient
664 public boolean isSpecies() {
665 return getRank().isSpecies();
666 }
667 @Transient
668 public boolean isInfraSpecific() {
669 return getRank().isInfraSpecific();
670 }
671
672
673 @Transient
674 abstract public NomenclaturalCode getNomeclaturalCode();
675
676 @Override
677 public String generateTitle() {
678 // TODO Auto-generated method stub
679 return null;
680 }
681
682
683 }