(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.common.IParsable;
20 import eu.etaxonomy.cdm.model.common.IRelated;
21 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
22 import eu.etaxonomy.cdm.model.common.IReferencedEntity;
23 import eu.etaxonomy.cdm.model.common.RelationshipBase;
24
25
26 import org.apache.log4j.Logger;
27 import org.hibernate.annotations.Cascade;
28 import org.hibernate.annotations.CascadeType;
29 import org.hibernate.annotations.Target;
30
31 import eu.etaxonomy.cdm.strategy.cache.INameCacheStrategy;
32
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 {@link taxon.Taxon "accepted" respectively "correct" (taxon) name}
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, S extends INameCacheStrategy> extends IdentifiableEntity<TaxonNameBase> implements IReferencedEntity, IParsable, IRelated {
57 static Logger logger = Logger.getLogger(TaxonNameBase.class);
58 //Non-atomised addition to a name not ruled by a nomenclatural code
59 private String appendedPhrase;
60 private String nomenclaturalMicroReference;
61 private boolean hasProblem = false;
62 protected Set<NameTypeDesignation> nameTypeDesignations = new HashSet<NameTypeDesignation>();
63 private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
64 private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
65 private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
66 private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
67 private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
68 private Rank rank;
69 private INomenclaturalReference nomenclaturalReference;
70
71 protected boolean protectedNameCache;
72
73 static Method methodTaxonBaseSetName;
74
75 // ************* CONSTRUCTORS *************/
76 /**
77 * Class constructor: creates a new empty taxon name instance.
78 *
79 * @see #TaxonNameBase(Rank)
80 * @see #TaxonNameBase(HomotypicalGroup)
81 * @see #TaxonNameBase(Rank, HomotypicalGroup)
82 */
83 public TaxonNameBase() {
84 this(null, null);
85 }
86 /**
87 * Class constructor: creates a new taxon name instance
88 * only containing its {@link common.Rank rank}.
89 *
90 * @param rank the rank to be assigned to this taxon name
91 * @see #TaxonNameBase()
92 * @see #TaxonNameBase(HomotypicalGroup)
93 * @see #TaxonNameBase(Rank, HomotypicalGroup)
94 */
95 public TaxonNameBase(Rank rank) {
96 this(rank, null);
97 }
98 /**
99 * Class constructor: creates a new taxon name instance
100 * only containing its {@link common.HomotypicalGroup homotypical group}.
101 * The new taxon name instance will be also added to the set of taxon names
102 * belonging to this homotypical group. If the homotypical group
103 * does not exist a new instance will be created for it.
104 *
105 * @param homotypicalGroup the homotypical group to which this taxon name belongs
106 * @see #TaxonNameBase()
107 * @see #TaxonNameBase(Rank)
108 * @see #TaxonNameBase(Rank, HomotypicalGroup)
109 */
110 public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
111 this(null, homotypicalGroup);
112 }
113 /**
114 * Class constructor: creates a new instance of a taxon name
115 * only containing its {@link common.Rank rank} and
116 * its {@link common.HomotypicalGroup homotypical group}.
117 *
118 * @param rank the rank to be assigned to this taxon name
119 * @param homotypicalGroup the homotypical group to which this taxon name belongs
120 * @see #TaxonNameBase()
121 * @see #TaxonNameBase(Rank)
122 * @see #TaxonNameBase(HomotypicalGroup)
123 */
124 public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
125 super();
126 this.setRank(rank);
127 if (homotypicalGroup == null){
128 homotypicalGroup = new HomotypicalGroup();
129 }
130 homotypicalGroup.addTypifiedName(this);
131 }
132
133 //********* METHODS **************************************/
134
135
136 /**
137 * Returns the boolean value "true" if the components of this taxon name
138 * follow the rules of the corresponding {@link NomenclaturalCode nomenclatural code},
139 * "false" otherwise. The nomenclatural code depends on
140 * the concrete name subclass ({@link BacterialName BacterialName},
141 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
142 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName})
143 * to which this taxon name belongs.
144 *
145 * @return the boolean value expressing the compliance of this taxon name to the nomenclatural code
146 */
147 @Transient
148 public abstract boolean isCodeCompliant();
149
150
151 /**
152 * Returns the set of all {@link NameRelationship name relationships}
153 * in which this taxon name is involved. A taxon name can be both source
154 * in some name relationships or target in some others.
155 *
156 * @see #getRelationsToThisName()
157 * @see #getRelationsFromThisName()
158 * @see #addNameRelationship(NameRelationship)
159 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
160 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
161 */
162 @Transient
163 public Set<NameRelationship> getNameRelations() {
164 Set<NameRelationship> rels = new HashSet<NameRelationship>();
165 rels.addAll(getRelationsFromThisName());
166 rels.addAll(getRelationsToThisName());
167 return rels;
168 }
169 /**
170 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from this taxon name to another taxon name
171 * and adds it both to the set of {@link #getRelationsFromThisName() relations from this taxon name} and
172 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
173 *
174 * @param toName the taxon name of the target for this new name relationship
175 * @param type the type of this new name relationship
176 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
177 * @see #getRelationsToThisName()
178 * @see #getNameRelations()
179 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
180 * @see #addNameRelationship(NameRelationship)
181 */
182 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
183 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
184 }
185 /**
186 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to this taxon name
187 * and adds it both to the set of {@link #getRelationsToThisName() relations to this taxon name} and
188 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
189 *
190 * @param fromName the taxon name of the source for this new name relationship
191 * @param type the type of this new name relationship
192 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
193 * @see #getRelationsFromThisName()
194 * @see #getNameRelations()
195 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
196 * @see #addNameRelationship(NameRelationship)
197 */
198 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
199 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
200 }
201 /**
202 * Adds an existing {@link NameRelationship name relationship} either to the set of
203 * {@link #getRelationsToThisName() relations to this taxon name} or to the set of
204 * {@link #getRelationsFromThisName() relations from this taxon name}. If neither the
205 * source nor the target of the name relationship match with this taxon
206 * no addition will be carried out.
207 *
208 * @param rel the name relationship to be added to one of this taxon name's name relationships sets
209 * @see #getNameRelations()
210 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
211 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
212 */
213 protected void addNameRelationship(NameRelationship rel) {
214 if (rel!=null && rel.getToName().equals(this)){
215 this.relationsToThisName.add(rel);
216 }else if(rel!=null && rel.getFromName().equals(this)){
217 this.relationsFromThisName.add(rel);
218 }else{
219 //TODO: raise error???
220 }
221 }
222 /**
223 * Removes one {@link NameRelationship name relationship} from one of both sets of
224 * {@link #getNameRelations() name relationships} in which this taxon name is involved.
225 * The name relationship will also be removed from one of both sets belonging
226 * to the second taxon name involved. Furthermore the fromName and toName
227 * attributes of the name relationship object will be nullified.
228 *
229 * @param nameRelation the name relationship which should be deleted from one of both sets
230 * @see #getNameRelations()
231 */
232 public void removeNameRelationship(NameRelationship nameRelation) {
233 //TODO to be implemented?
234 logger.warn("not yet fully implemented?");
235 this.relationsToThisName.remove(nameRelation);
236 this.relationsFromThisName.remove(nameRelation);
237 }
238
239
240 public void addRelationship(RelationshipBase relation) {
241 if (relation instanceof NameRelationship){
242 addNameRelationship((NameRelationship)relation);
243 }else{
244 //TODO exception handling
245 }
246 }
247
248
249 /**
250 * Returns the set of all {@link NameRelationship name relationships}
251 * in which this taxon name is involved as a source.
252 *
253 * @see #getNameRelations()
254 * @see #getRelationsToThisName()
255 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
256 */
257 @OneToMany(mappedBy="relatedFrom", fetch= FetchType.EAGER)
258 @Cascade({CascadeType.SAVE_UPDATE})
259 public Set<NameRelationship> getRelationsFromThisName() {
260 return relationsFromThisName;
261 }
262 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
263 this.relationsFromThisName = relationsFromThisName;
264 }
265
266 /**
267 * Returns the set of all {@link NameRelationship name relationships}
268 * in which this taxon name is involved as a target.
269 *
270 * @see #getNameRelations()
271 * @see #getRelationsFromThisName()
272 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
273 */
274 @OneToMany(mappedBy="relatedTo", fetch= FetchType.EAGER)
275 @Cascade({CascadeType.SAVE_UPDATE})
276 public Set<NameRelationship> getRelationsToThisName() {
277 return relationsToThisName;
278 }
279 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
280 this.relationsToThisName = relationsToThisName;
281 }
282
283
284 /**
285 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
286 * to this taxon name according to its corresponding nomenclature code.
287 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
288 * and the nomenclatural code rule considered.
289 *
290 * @see NomenclaturalStatus
291 * @see NomenclaturalStatusType
292 */
293 @OneToMany(fetch= FetchType.EAGER)
294 @Cascade({CascadeType.SAVE_UPDATE})
295 public Set<NomenclaturalStatus> getStatus() {
296 return status;
297 }
298 /**
299 * @see #getStatus()
300 */
301 protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
302 this.status = nomStatus;
303 }
304 /**
305 * Adds a new {@link NomenclaturalStatus nomenclatural status}
306 * to this taxon name's set of nomenclatural status.
307 *
308 * @param nomStatus the nomenclatural status to be added
309 * @see #getStatus()
310 */
311 public void addStatus(NomenclaturalStatus nomStatus) {
312 this.status.add(nomStatus);
313 }
314 /**
315 * Removes one element from the set of nomenclatural status of this taxon name.
316 * Type and ruleConsidered attributes of the nomenclatural status object
317 * will be nullified.
318 *
319 * @param nomStatus the nomenclatural status of this taxon name which should be deleted
320 * @see #getStatus()
321 */
322 public void removeStatus(NomenclaturalStatus nomStatus) {
323 //TODO to be implemented?
324 logger.warn("not yet fully implemented?");
325 this.status.remove(nomStatus);
326 }
327
328
329 /**
330 * Indicates if this taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
331 * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
332 * of any other taxon name. Returns true, if a basionym or a replaced synonym
333 * relationship from this taxon name to another taxon name exists,
334 * false otherwise (also in case this taxon name is the only one in the
335 * homotypical group).
336 */
337 @Transient
338 public boolean isOriginalCombination(){
339 Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
340 for (NameRelationship relation : relationsFromThisName) {
341 if (relation.getType().equals(NameRelationshipType.BASIONYM()) ||
342 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM())) {
343 return true;
344 }
345 }
346 return false;
347 }
348
349 /**
350 * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
351 * The basionym of a taxon name is its epithet-bringing synonym.
352 * For instance Pinus abies L. was published by Linnaeus and the botanist
353 * Karsten transferred later this taxon to the genus Picea. Therefore,
354 * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
355 */
356 @Transient
357 public T getBasionym(){
358 //TODO: pick the right name relationships...
359 return null;
360 }
361 /**
362 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
363 * The basionym relationship will be added to this taxon name
364 * and to the basionym. The basionym cannot have itself a basionym.
365 *
366 * @see #getBasionym()
367 * @see #setBasionym(TaxonNameBase, String)
368 */
369 public void setBasionym(T basionym){
370 setBasionym(basionym, null);
371 }
372 /**
373 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name
374 * and keeps the nomenclatural rule considered for it. The basionym
375 * relationship will be added to this taxon name and to the basionym.
376 * The basionym cannot have itself a basionym.
377 *
378 * @see #getBasionym()
379 * @see #setBasionym(TaxonNameBase)
380 */
381 public void setBasionym(T basionym, String ruleConsidered){
382 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
383 }
384
385
386
387 @Transient
388 public abstract S getCacheStrategy();
389 public abstract void setCacheStrategy(S cacheStrategy);
390
391 /**
392 * Returns the taxonomic {@link Rank rank} of this taxon name.
393 *
394 * @see Rank
395 */
396 @ManyToOne
397 //@Cascade({CascadeType.SAVE_UPDATE})
398 public Rank getRank(){
399 return this.rank;
400 }
401 /**
402 * @see #getRank()
403 */
404 public void setRank(Rank rank){
405 this.rank = rank;
406 }
407
408 /**
409 * Returns the {@link reference.INomenclaturalReference nomenclatural reference} of this taxon name.
410 * The nomenclatural reference is here meant to be the one publication
411 * this taxon name was originally published in while fulfilling the formal
412 * requirements as specified by the corresponding nomenclatural code.
413 *
414 * @see reference.INomenclaturalReference
415 * @see reference.ReferenceBase
416 */
417 @ManyToOne
418 @Cascade({CascadeType.SAVE_UPDATE})
419 @Target(ReferenceBase.class)
420 public INomenclaturalReference getNomenclaturalReference(){
421 return (INomenclaturalReference) this.nomenclaturalReference;
422 }
423 /**
424 * Assigns a nomenclatural {@link reference.INomenclaturalReference nomenclatural reference} to this taxon name.
425 * The corresponding {@link reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
426 * as it is obviously used for nomenclatural purposes.
427 *
428 * @see #getNomenclaturalReference()
429 */
430 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
431 this.nomenclaturalReference = nomenclaturalReference;
432 }
433
434 /**
435 * Returns the appended phrase string assigned to this taxon name.
436 * The appended phrase is a non-atomised addition to a name. It is
437 * not ruled by a nomenclatural code.
438 */
439 public String getAppendedPhrase(){
440 return this.appendedPhrase;
441 }
442 /**
443 * @see #getAppendedPhrase()
444 */
445 public void setAppendedPhrase(String appendedPhrase){
446 this.appendedPhrase = appendedPhrase;
447 }
448
449 /**
450 * Returns the details string of the nomenclatural reference assigned
451 * to this taxon name. The details describe the exact localisation within
452 * the publication used as nomenclature reference. These are mostly
453 * (implicitly) pages but can also be figures or tables or any other
454 * element of a publication. A nomenclatural micro reference (details)
455 * requires the existence of a nomenclatural reference.
456 */
457 //Details of the nomenclatural reference (protologue).
458 public String getNomenclaturalMicroReference(){
459 return this.nomenclaturalMicroReference;
460 }
461 /**
462 * @see #getNomenclaturalMicroReference()
463 */
464 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
465 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
466 }
467
468 /**
469 * Returns the boolean value of the flag indicating whether the used {@link eu.etaxonomy.cdm.strategy.parser.INonViralNameParser parser}
470 * method was able to parse the taxon name string successfully (false)
471 * or not (true).
472 *
473 * @return the boolean value of the hasProblem flag
474 * @see #getNameCache()
475 */
476 public boolean getHasProblem(){
477 return this.hasProblem;
478 }
479 /**
480 * @see #getHasProblem()
481 */
482 public void setHasProblem(boolean hasProblem){
483 this.hasProblem = hasProblem;
484 }
485 /**
486 * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.
487 *
488 * @see #getHasProblem()
489 */
490 public boolean hasProblem(){
491 return getHasProblem();
492 }
493
494
495 /**
496 * Returns the set of {@link NameTypeDesignation name type designations} assigned
497 * to this taxon name the rank of which must be above "species".
498 * The name type designations include all the taxon names used to typify
499 * this name and eventually the rejected or conserved status
500 * of these designations.
501 *
502 * @see NameTypeDesignation
503 * @see SpecimenTypeDesignation
504 */
505 @OneToMany
506 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
507 @Cascade(CascadeType.SAVE_UPDATE)
508 public Set<NameTypeDesignation> getNameTypeDesignations() {
509 return nameTypeDesignations;
510 }
511 /**
512 * @see #getNameTypeDesignations()
513 */
514 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
515 this.nameTypeDesignations = nameTypeDesignations;
516 }
517
518 /**
519 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} assigned
520 * indirectly to this taxon name through its {@link HomotypicalGroup homotypical group}.
521 * The rank of this taxon name is generally "species" or below.
522 * The specimen type designations include all the specimens on which
523 * the typification of this name is based (and which are common to all
524 * taxon names belonging to the homotypical group) and eventually
525 * the status of these designations.
526 *
527 * @see SpecimenTypeDesignation
528 * @see NameTypeDesignation
529 */
530 @Transient
531 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
532 return this.getHomotypicalGroup().getTypeDesignations();
533 }
534
535 /**
536 * Creates and adds a new {@link NameTypeDesignation name type designation}
537 * to this taxon name's set of name type designations.
538 *
539 * @param typeSpecies the taxon name to be used as type of this taxon name
540 * @param citation the reference for this new designation
541 * @param citationMicroReference the string with the details (generally pages) within the reference
542 * @param originalNameString the taxon name used in the reference to assert this designation
543 * @param isRejectedType the boolean status for rejected
544 * @param isConservedType the boolean status for conserved
545 * @see #getNameTypeDesignations()
546 * @see #addTypeDesignation(Specimen, TypeDesignationStatus, ReferenceBase, String, String)
547 */
548 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
549 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
550 }
551 /**
552 * Adds a new {@link SpecimenTypeDesignation specimen type designation}
553 * to the set of specimen type designations assigned to the
554 * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
555 *
556 * @param typeSpecimen the specimen to be used as a type for this taxon name's homotypical group
557 * @param status the specimen type designation status
558 * @param citation the reference for this new specimen type designation
559 * @param citationMicroReference the string with the details (generally pages) within the reference
560 * @param originalNameString the taxon name used in the reference to assert this designation
561 * @see HomotypicalGroup#getTypeDesignations()
562 * @see #addTypeDesignation(TaxonNameBase, ReferenceBase, String, String, boolean, boolean)
563 * @see TypeDesignationStatus
564 */
565 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
566 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
567 }
568 /**
569 * Removes one element from the set of {@link NameTypeDesignation name type designations} of this taxon name.
570 * The name type designation itself will be nullified.
571 *
572 * @param typeDesignation the name type designation of this taxon name which should be deleted
573 * @see #getNameTypeDesignations()
574 * @see #removeTypeDesignation(SpecimenTypeDesignation)
575 */
576 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
577 logger.warn("not yet fully implemented: nullify the name type designation itself?");
578 this.nameTypeDesignations.remove(typeDesignation);
579 }
580 /**
581 * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
582 * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
583 * The specimen type designation itself will be nullified.
584 *
585 * @param typeDesignation the specimen type designation which should be deleted
586 * @see HomotypicalGroup#getTypeDesignations()
587 * @see #removeTypeDesignation(NameTypeDesignation)
588 */
589 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
590 logger.warn("not yet fully implemented: nullify the specimen type designation itself?");
591 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
592 }
593
594 /**
595 * Returns the {@link HomotypicalGroup homotypical group} to which
596 * this taxon name belongs. A homotypical group represents all taxon names
597 * that share the same type specimens.
598 *
599 * @see HomotypicalGroup
600 */
601 @ManyToOne
602 @Cascade({CascadeType.SAVE_UPDATE})
603 public HomotypicalGroup getHomotypicalGroup() {
604 return homotypicalGroup;
605 }
606 @Deprecated //only for bidirectional and persistence use
607 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
608 this.homotypicalGroup = newHomotypicalGroup;
609 }
610
611 @Transient
612 public StrictReferenceBase getCitation(){
613 //TODO What is the purpose of this method differing from the getNomenclaturalReference method?
614 logger.warn("getCitation not yet implemented");
615 return null;
616 }
617
618 /**
619 * Returns the complete string containing the
620 * {@link reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
621 * (including {@link #getNomenclaturalMicroReference() details}) assigned to this taxon name.
622 *
623 * @see reference.INomenclaturalReference#getNomenclaturalCitation()
624 * @see #getNomenclaturalReference()
625 * @see #getNomenclaturalMicroReference()
626 */
627 @Transient
628 public String getCitationString(){
629 logger.warn("getCitationString not yet implemented");
630 return null;
631 }
632
633 @Transient
634 public String[] getProblems(){
635 logger.warn("getProblems not yet implemented");
636 return null;
637 }
638
639 /**
640 * Returns the string containing the publication date (generally only year)
641 * of the nomenclatural reference, null if there is no nomenclatural
642 * reference.
643 *
644 * @see reference.INomenclaturalReference#getYear()
645 */
646 @Transient
647 public String getReferenceYear(){
648 if (this.getNomenclaturalReference() != null ){
649 return this.getNomenclaturalReference().getYear();
650 }else{
651 return null;
652 }
653 }
654
655 /**
656 * Returns the set of {@link taxon.TaxonBase taxon bases} that refer to this taxon name.
657 * In this context a taxon base means the use of a taxon name by a reference
658 * either as a taxon ("accepted/correct" name) or as a (junior) synonym.
659 * A taxon name can be used by several distinct references but only once
660 * within a taxonomic treatment (identified by one reference).
661 *
662 * @see taxon.TaxonBase
663 * @see #getTaxa()
664 * @see #getSynonyms()
665 */
666 @OneToMany(mappedBy="name", fetch= FetchType.EAGER)
667 public Set<TaxonBase> getTaxonBases() {
668 return this.taxonBases;
669 }
670 /**
671 * @see #getTaxonBases()
672 */
673 protected void setTaxonBases(Set<TaxonBase> taxonBases) {
674 if (taxonBases == null){
675 taxonBases = new HashSet<TaxonBase>();
676 }else{
677 this.taxonBases = taxonBases;
678 }
679 }
680 /**
681 * Adds a new {@link taxon.TaxonBase taxon base}
682 * to the set of taxon bases using this taxon name.
683 *
684 * @param taxonBase the taxon base to be added
685 * @see #getTaxonBases()
686 */
687 //TODO protected
688 public void addTaxonBase(TaxonBase taxonBase){
689 taxonBases.add(taxonBase);
690 initMethods();
691 invokeSetMethod(methodTaxonBaseSetName, taxonBase);
692 }
693 public void removeTaxonBase(TaxonBase taxonBase){
694 taxonBases.remove(taxonBase);
695 initMethods();
696 invokeSetMethodWithNull(methodTaxonBaseSetName, taxonBase);
697 }
698
699 private void initMethods(){
700 if (methodTaxonBaseSetName == null){
701 try {
702 methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
703 methodTaxonBaseSetName.setAccessible(true);
704 } catch (Exception e) {
705 e.printStackTrace();
706 //TODO handle exception
707 }
708 }
709 }
710
711
712 /**
713 * Returns the set of {@link taxon.Taxon taxa} ("accepted/correct" names according to any
714 * reference) that are based on this taxon name. This set is a subset of
715 * the set returned by getTaxonBases().
716 *
717 * @see taxon.Taxon
718 * @see #getTaxonBases()
719 * @see #getSynonyms()
720 */
721 @Transient
722 public Set<Taxon> getTaxa(){
723 Set<Taxon> result = new HashSet<Taxon>();
724 for (TaxonBase taxonBase : this.taxonBases){
725 if (taxonBase instanceof Taxon){
726 result.add((Taxon)taxonBase);
727 }
728 }
729 return result;
730 }
731
732 /**
733 * Returns the set of {@link taxon.Synonym (junior) synonyms} (according to any
734 * reference) that are based on this taxon name. This set is a subset of
735 * the set returned by getTaxonBases().
736 *
737 * @see taxon.Synonym
738 * @see #getTaxonBases()
739 * @see #getTaxa()
740 */
741 @Transient
742 public Set<Synonym> getSynonyms() {
743 Set<Synonym> result = new HashSet<Synonym>();
744 for (TaxonBase taxonBase : this.taxonBases){
745 if (taxonBase instanceof Synonym){
746 result.add((Synonym)taxonBase);
747 }
748 }
749 return result;
750 }
751
752 // ***********
753 /**
754 * Returns the boolean value indicating whether a given taxon name belongs
755 * to the same {@link HomotypicalGroup homotypical group} as this taxon name (true)
756 * or not (false). Returns "true" only if the homotypical groups of both
757 * taxon names exist and if they are identical.
758 *
759 * @param homoTypicName the taxon name the homotypical group of which is to be checked
760 * @return the boolean value of the check
761 * @see HomotypicalGroup
762 */
763 public boolean isHomotypic(TaxonNameBase homoTypicName) {
764 if (homoTypicName == null) {
765 return false;
766 }
767 HomotypicalGroup homotypicGroup = homoTypicName.getHomotypicalGroup();
768 if (homotypicGroup == null || this.getHomotypicalGroup() == null) {
769 return false;
770 }
771 if (homotypicGroup.equals(this.getHomotypicalGroup())) {
772 return true;
773 }
774 return false;
775 }
776
777
778
779 //********* Rank comparison shortcuts ********************//
780 @Transient
781 public boolean isSupraGeneric() {
782 return getRank().isSupraGeneric();
783 }
784 @Transient
785 public boolean isGenus() {
786 return getRank().isGenus();
787 }
788 @Transient
789 public boolean isInfraGeneric() {
790 return getRank().isInfraGeneric();
791 }
792 @Transient
793 public boolean isSpecies() {
794 return getRank().isSpecies();
795 }
796 @Transient
797 public boolean isInfraSpecific() {
798 return getRank().isInfraSpecific();
799 }
800
801
802 @Transient
803 abstract public NomenclaturalCode getNomeclaturalCode();
804
805 @Override
806 public String generateTitle() {
807 // TODO Auto-generated method stub
808 return null;
809 }
810
811
812 }