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