c972a6eeff083dc6adfa67a8b1ffce1422154a7c
[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 {
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(RelationshipBase relation) {
320 if (relation instanceof NameRelationship){
321 addNameRelationship((NameRelationship)relation);
322 }else{
323 //TODO exception handling
324 }
325 }
326
327
328 /**
329 * Returns the set of all {@link NameRelationship name relationships}
330 * in which this taxon name is involved as a source.
331 *
332 * @see #getNameRelations()
333 * @see #getRelationsToThisName()
334 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
335 */
336 @OneToMany(mappedBy="relatedFrom", fetch= FetchType.EAGER)
337 @Cascade({CascadeType.SAVE_UPDATE})
338 public Set<NameRelationship> getRelationsFromThisName() {
339 return relationsFromThisName;
340 }
341 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
342 this.relationsFromThisName = relationsFromThisName;
343 }
344
345 /**
346 * Returns the set of all {@link NameRelationship name relationships}
347 * in which this taxon name is involved as a target.
348 *
349 * @see #getNameRelations()
350 * @see #getRelationsFromThisName()
351 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
352 */
353 @OneToMany(mappedBy="relatedTo", fetch= FetchType.EAGER)
354 @Cascade({CascadeType.SAVE_UPDATE})
355 public Set<NameRelationship> getRelationsToThisName() {
356 return relationsToThisName;
357 }
358 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
359 this.relationsToThisName = relationsToThisName;
360 }
361
362
363 /**
364 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
365 * to this taxon name according to its corresponding nomenclature code.
366 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
367 * and the nomenclatural code rule considered.
368 *
369 * @see NomenclaturalStatus
370 * @see NomenclaturalStatusType
371 */
372 @OneToMany(fetch= FetchType.EAGER)
373 @Cascade({CascadeType.SAVE_UPDATE})
374 public Set<NomenclaturalStatus> getStatus() {
375 return status;
376 }
377 /**
378 * @see #getStatus()
379 */
380 protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
381 this.status = nomStatus;
382 }
383 /**
384 * Adds a new {@link NomenclaturalStatus nomenclatural status}
385 * to this taxon name's set of nomenclatural status.
386 *
387 * @param nomStatus the nomenclatural status to be added
388 * @see #getStatus()
389 */
390 public void addStatus(NomenclaturalStatus nomStatus) {
391 this.status.add(nomStatus);
392 }
393 /**
394 * Removes one element from the set of nomenclatural status of this taxon name.
395 * Type and ruleConsidered attributes of the nomenclatural status object
396 * will be nullified.
397 *
398 * @param nomStatus the nomenclatural status of this taxon name which should be deleted
399 * @see #getStatus()
400 */
401 public void removeStatus(NomenclaturalStatus nomStatus) {
402 //TODO to be implemented?
403 logger.warn("not yet fully implemented?");
404 this.status.remove(nomStatus);
405 }
406
407
408 /**
409 * Indicates if this taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
410 * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
411 * of any other taxon name. Returns true, if a basionym or a replaced synonym
412 * relationship from this taxon name to another taxon name exists,
413 * false otherwise (also in case this taxon name is the only one in the
414 * homotypical group).
415 */
416 @Transient
417 public boolean isOriginalCombination(){
418 Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
419 for (NameRelationship relation : relationsFromThisName) {
420 if (relation.getType().equals(NameRelationshipType.BASIONYM()) ||
421 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM())) {
422 return true;
423 }
424 }
425 return false;
426 }
427
428 /**
429 * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
430 * The basionym of a taxon name is its epithet-bringing synonym.
431 * For instance Pinus abies L. was published by Linnaeus and the botanist
432 * Karsten transferred later this taxon to the genus Picea. Therefore,
433 * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
434 */
435 @Transient
436 public T getBasionym(){
437 //TODO: pick the right name relationships...
438 return null;
439 }
440 /**
441 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
442 * The basionym relationship will be added to this taxon name
443 * and to the basionym. The basionym cannot have itself a basionym.
444 *
445 * @see #getBasionym()
446 * @see #setBasionym(TaxonNameBase, String)
447 */
448 public void setBasionym(T basionym){
449 setBasionym(basionym, null);
450 }
451 /**
452 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name
453 * and keeps the nomenclatural rule considered for it. The basionym
454 * relationship will be added to this taxon name and to the basionym.
455 * The basionym cannot have itself a basionym.
456 *
457 * @see #getBasionym()
458 * @see #setBasionym(TaxonNameBase)
459 */
460 public void setBasionym(T basionym, String ruleConsidered){
461 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
462 }
463
464
465
466 //TODO for PROTOTYPE
467 @Transient
468 public INameCacheStrategy<T> getCacheStrategy() {
469 return cacheStrategy;
470 }
471 public void setCacheStrategy(INameCacheStrategy cacheStrategy) {
472 this.cacheStrategy = cacheStrategy;
473 }
474
475 @ManyToOne
476 //@Cascade({CascadeType.SAVE_UPDATE})
477 public Rank getRank(){
478 return this.rank;
479 }
480 public void setRank(Rank rank){
481 this.rank = rank;
482 }
483
484 @ManyToOne
485 @Cascade({CascadeType.SAVE_UPDATE})
486 public ReferenceBase getNomenclaturalReference(){
487 return (ReferenceBase) this.nomenclaturalReference;
488 }
489 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
490 this.nomenclaturalReference = nomenclaturalReference;
491 }
492
493
494 public String getAppendedPhrase(){
495 return this.appendedPhrase;
496 }
497 public void setAppendedPhrase(String appendedPhrase){
498 this.appendedPhrase = appendedPhrase;
499 }
500
501 public String getNomenclaturalMicroReference(){
502 return this.nomenclaturalMicroReference;
503 }
504 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
505 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
506 }
507
508 public boolean getHasProblem(){
509 return this.hasProblem;
510 }
511 public void setHasProblem(boolean hasProblem){
512 this.hasProblem = hasProblem;
513 }
514 /**
515 * Same as getHasProblem()
516 * @return
517 */
518 public boolean hasProblem(){
519 return getHasProblem();
520 }
521
522
523 @OneToMany
524 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
525 @Cascade(CascadeType.SAVE_UPDATE)
526 public Set<NameTypeDesignation> getNameTypeDesignations() {
527 return nameTypeDesignations;
528 }
529 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
530 this.nameTypeDesignations = nameTypeDesignations;
531 }
532
533 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
534 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
535 }
536 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
537 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
538 }
539 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
540 this.nameTypeDesignations.remove(typeDesignation);
541 }
542 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
543 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
544 }
545
546
547 @ManyToOne
548 @Cascade({CascadeType.SAVE_UPDATE})
549 public HomotypicalGroup getHomotypicalGroup() {
550 return homotypicalGroup;
551 }
552 @Deprecated //only for bidirectional and persistence use
553 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
554 this.homotypicalGroup = newHomotypicalGroup;
555 }
556
557 @Transient
558 public StrictReferenceBase getCitation(){
559 logger.warn("getCitation not yet implemented");
560 return null;
561 }
562
563 @Transient
564 public String getCitationString(){
565 logger.warn("getCitationString not yet implemented");
566 return null;
567 }
568
569 @Transient
570 public String[] getProblems(){
571 logger.warn("getProblems not yet implemented");
572 return null;
573 }
574
575 /**
576 * returns year of according nomenclatural reference, null if nomenclatural
577 * reference does not exist
578 */
579 @Transient
580 public String getReferenceYear(){
581 if (this.getNomenclaturalReference() != null ){
582 return this.getNomenclaturalReference().getYear();
583 }else{
584 return null;
585 }
586 }
587
588 @OneToMany(mappedBy="name", fetch= FetchType.EAGER)
589 public Set<TaxonBase> getTaxonBases() {
590 return this.taxonBases;
591 }
592 protected void setTaxonBases(Set<TaxonBase> taxonBases) {
593 if (taxonBases == null){
594 taxonBases = new HashSet<TaxonBase>();
595 }else{
596 this.taxonBases = taxonBases;
597 }
598 }
599 //TODO protected
600 public void addTaxonBase(TaxonBase taxonBase){
601 taxonBases.add(taxonBase);
602 initMethods();
603 invokeSetMethod(methodTaxonBaseSetName, taxonBase);
604 }
605
606 private void initMethods(){
607 if (methodTaxonBaseSetName == null){
608 try {
609 methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
610 methodTaxonBaseSetName.setAccessible(true);
611 } catch (Exception e) {
612 e.printStackTrace();
613 //TODO handle exception
614 }
615 }
616 }
617
618
619 /**
620 * Return a set of taxa that use this name.
621 * @return Set<Taxon> The set of taxa this TaxonName belongs to
622 */
623 @Transient
624 public Set<Taxon> getTaxa(){
625 Set<Taxon> result = new HashSet<Taxon>();
626 for (TaxonBase taxonBase : this.taxonBases){
627 if (taxonBase instanceof Taxon){
628 result.add((Taxon)taxonBase);
629 }
630 }
631 return result;
632 }
633
634 /**
635 * Return a set of synonyms that use this name
636 * @return The set of synonyms this TaxonName belongs to
637 */
638 @Transient
639 public Set<Synonym> getSynonyms() {
640 Set<Synonym> result = new HashSet<Synonym>();
641 for (TaxonBase taxonBase : this.taxonBases){
642 if (taxonBase instanceof Synonym){
643 result.add((Synonym)taxonBase);
644 }
645 }
646 return result;
647 }
648
649 @Transient
650 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
651 return this.getHomotypicalGroup().getTypeDesignations();
652 }
653
654 // ***********
655 public boolean isHomotypic(TaxonNameBase homoTypicName) {
656 if (homoTypicName == null) {
657 return false;
658 }
659 HomotypicalGroup homotypicGroup = homoTypicName.getHomotypicalGroup();
660 if (homotypicGroup == null || this.getHomotypicalGroup() == null) {
661 return false;
662 }
663 if (homotypicGroup.equals(this.getHomotypicalGroup())) {
664 return true;
665 }
666 return false;
667 }
668
669
670
671 //********* Rank comparison shortcuts ********************//
672 @Transient
673 public boolean isSupraGeneric() {
674 return getRank().isSupraGeneric();
675 }
676 @Transient
677 public boolean isGenus() {
678 return getRank().isGenus();
679 }
680 @Transient
681 public boolean isInfraGeneric() {
682 return getRank().isInfraGeneric();
683 }
684 @Transient
685 public boolean isSpecies() {
686 return getRank().isSpecies();
687 }
688 @Transient
689 public boolean isInfraSpecific() {
690 return getRank().isInfraSpecific();
691 }
692
693
694 @Transient
695 abstract public NomenclaturalCode getNomeclaturalCode();
696
697 @Override
698 public String generateTitle() {
699 // TODO Auto-generated method stub
700 return null;
701 }
702
703
704 }