2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.name
;
12 import java
.lang
.reflect
.Method
;
13 import java
.util
.HashSet
;
16 import javax
.persistence
.Entity
;
17 import javax
.persistence
.FetchType
;
18 import javax
.persistence
.Inheritance
;
19 import javax
.persistence
.InheritanceType
;
20 import javax
.persistence
.ManyToMany
;
21 import javax
.persistence
.ManyToOne
;
22 import javax
.persistence
.OneToMany
;
23 import javax
.persistence
.Transient
;
24 import javax
.xml
.bind
.annotation
.XmlAccessType
;
25 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
26 import javax
.xml
.bind
.annotation
.XmlAnyElement
;
27 import javax
.xml
.bind
.annotation
.XmlAttribute
;
28 import javax
.xml
.bind
.annotation
.XmlElement
;
29 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
30 import javax
.xml
.bind
.annotation
.XmlIDREF
;
31 import javax
.xml
.bind
.annotation
.XmlRootElement
;
32 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
33 import javax
.xml
.bind
.annotation
.XmlTransient
;
34 import javax
.xml
.bind
.annotation
.XmlType
;
36 import org
.apache
.log4j
.Logger
;
37 import org
.hibernate
.annotations
.Cascade
;
38 import org
.hibernate
.annotations
.CascadeType
;
39 import org
.hibernate
.annotations
.Index
;
40 import org
.hibernate
.annotations
.Table
;
41 import org
.hibernate
.annotations
.Target
;
43 import eu
.etaxonomy
.cdm
.model
.common
.IParsable
;
44 import eu
.etaxonomy
.cdm
.model
.common
.IReferencedEntity
;
45 import eu
.etaxonomy
.cdm
.model
.common
.IRelated
;
46 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
47 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
48 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
49 import eu
.etaxonomy
.cdm
.model
.occurrence
.Specimen
;
50 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
51 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
52 import eu
.etaxonomy
.cdm
.model
.reference
.StrictReferenceBase
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
56 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INameCacheStrategy
;
59 * The upmost (abstract) class for scientific taxon names regardless of any
60 * particular {@link NomenclaturalCode nomenclature code}. The scientific taxon name does not depend
61 * on the use made of it in a publication or a treatment
62 * ({@link taxon.TaxonBase taxon concept respectively potential taxon})
63 * as an {@link taxon.Taxon "accepted" respectively "correct" (taxon) name}
64 * or as a {@link taxon.Synonym synonym}.
66 * This class corresponds partially to: <ul>
67 * <li> TaxonName according to the TDWG ontology
68 * <li> ScientificName and CanonicalName according to the TCS
69 * <li> ScientificName according to the ABCD schema
74 * @created 08-Nov-2007 13:06:57
76 @XmlAccessorType(XmlAccessType
.FIELD
)
77 @XmlType(name
= "TaxonNameBase", propOrder
= {
79 "nomenclaturalMicroReference",
80 "nomenclaturalReference",
83 "nameTypeDesignations",
84 "specimenTypeDesignations",
85 "relationsFromThisName",
86 "relationsToThisName",
91 @XmlRootElement(name
= "TaxonNameBase")
93 @Inheritance(strategy
=InheritanceType
.SINGLE_TABLE
)
94 @Table(appliesTo
="TaxonNameBase", indexes
= { @Index(name
= "taxonNameBaseTitleCacheIndex", columnNames
= { "persistentTitleCache" }) })
95 public abstract class TaxonNameBase
<T
extends TaxonNameBase
, S
extends INameCacheStrategy
> extends IdentifiableEntity
<TaxonNameBase
> implements IReferencedEntity
, IParsable
, IRelated
{
97 static Logger logger
= Logger
.getLogger(TaxonNameBase
.class);
99 private static Method methodDescriptionSetTaxonName
;
101 @XmlElementWrapper(name
= "Descriptions")
102 @XmlElement(name
= "Description")
103 private Set
<TaxonNameDescription
> descriptions
= new HashSet
<TaxonNameDescription
>();
105 @XmlElement(name
= "AppendedPhrase")
106 private String appendedPhrase
;
108 @XmlElement(name
= "NomenclaturalMicroReference")
109 private String nomenclaturalMicroReference
;
112 private boolean hasProblem
= false;
114 @XmlElementWrapper(name
= "TypeDesignations")
115 @XmlElement(name
= "TypeDesignation")
116 private Set
<TypeDesignationBase
> typeDesignations
= new HashSet
<TypeDesignationBase
>();
118 // List homotypical groups here in TaxonomicNames or separately?
119 // FIXME: Stack overflow if listed here.
120 @XmlElement(name
= "HomotypicalGroup")
122 @XmlSchemaType(name
= "IDREF")
123 private HomotypicalGroup homotypicalGroup
= new HomotypicalGroup();
125 @XmlElementWrapper(name
= "RelationsFromThisName")
126 @XmlElement(name
= "RelationFromThisName")
128 private Set
<NameRelationship
> relationsFromThisName
= new HashSet
<NameRelationship
>();
130 @XmlElementWrapper(name
= "RelationsToThisName")
131 @XmlElement(name
= "RelationToThisName")
133 private Set
<NameRelationship
> relationsToThisName
= new HashSet
<NameRelationship
>();
135 @XmlElementWrapper(name
= "Statuses")
136 @XmlElement(name
= "Status")
138 private Set
<NomenclaturalStatus
> status
= new HashSet
<NomenclaturalStatus
>();
141 //@XmlElementWrapper(name = "TaxonBases")
142 //@XmlElement(name = "TaxonBase")
143 private Set
<TaxonBase
> taxonBases
= new HashSet
<TaxonBase
>();
145 @XmlElement(name
= "Rank")
147 @XmlSchemaType(name
= "IDREF")
150 // FIXME: This must be an IDREF to the corresponding nomenclatural reference.
152 private INomenclaturalReference nomenclaturalReference
;
154 static Method methodTaxonBaseSetName
;
156 // ************* CONSTRUCTORS *************/
158 * Class constructor: creates a new empty taxon name.
160 * @see #TaxonNameBase(Rank)
161 * @see #TaxonNameBase(HomotypicalGroup)
162 * @see #TaxonNameBase(Rank, HomotypicalGroup)
164 public TaxonNameBase() {
168 * Class constructor: creates a new taxon name
169 * only containing its {@link common.Rank rank}.
171 * @param rank the rank to be assigned to <i>this</i> taxon name
172 * @see #TaxonNameBase()
173 * @see #TaxonNameBase(HomotypicalGroup)
174 * @see #TaxonNameBase(Rank, HomotypicalGroup)
176 public TaxonNameBase(Rank rank
) {
180 * Class constructor: creates a new taxon name
181 * only containing its {@link HomotypicalGroup homotypical group}.
182 * The new taxon name will be also added to the set of taxon names
183 * belonging to this homotypical group.
185 * @param homotypicalGroup the homotypical group to which <i>this</i> taxon name belongs
186 * @see #TaxonNameBase()
187 * @see #TaxonNameBase(Rank)
188 * @see #TaxonNameBase(Rank, HomotypicalGroup)
190 public TaxonNameBase(HomotypicalGroup homotypicalGroup
) {
191 this(null, homotypicalGroup
);
194 * Class constructor: creates a new taxon name
195 * only containing its {@link common.Rank rank} and
196 * its {@link HomotypicalGroup homotypical group}.
197 * The new taxon name will be also added to the set of taxon names
198 * belonging to this homotypical group.
200 * @param rank the rank to be assigned to <i>this</i> taxon name
201 * @param homotypicalGroup the homotypical group to which <i>this</i> taxon name belongs
202 * @see #TaxonNameBase()
203 * @see #TaxonNameBase(Rank)
204 * @see #TaxonNameBase(HomotypicalGroup)
206 public TaxonNameBase(Rank rank
, HomotypicalGroup homotypicalGroup
) {
209 if (homotypicalGroup
== null){
210 homotypicalGroup
= new HomotypicalGroup();
212 homotypicalGroup
.addTypifiedName(this);
215 //********* METHODS **************************************/
217 //@Index(name="TaxonNameBaseTitleCacheIndex")
218 // public String getTitleCache(){
219 // return super.getTitleCache();
223 * Returns the boolean value "false" since the components of <i>this</i> taxon name
224 * cannot follow the rules of a corresponding {@link NomenclaturalCode nomenclatural code}
225 * which is not defined for this class. The nomenclature code depends on
226 * the concrete name subclass ({@link BacterialName BacterialName},
227 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
228 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName})
229 * to which a taxon name belongs.
234 public abstract boolean isCodeCompliant();
238 * Returns the set of all {@link NameRelationship name relationships}
239 * in which <i>this</i> taxon name is involved. A taxon name can be both source
240 * in some name relationships or target in some others.
242 * @see #getRelationsToThisName()
243 * @see #getRelationsFromThisName()
244 * @see #addNameRelationship(NameRelationship)
245 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
246 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
249 public Set
<NameRelationship
> getNameRelations() {
250 Set
<NameRelationship
> rels
= new HashSet
<NameRelationship
>();
251 rels
.addAll(getRelationsFromThisName());
252 rels
.addAll(getRelationsToThisName());
256 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from <i>this</i> taxon name to another taxon name
257 * and adds it both to the set of {@link #getRelationsFromThisName() relations from <i>this</i> taxon name} and
258 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
260 * @param toName the taxon name of the target for this new name relationship
261 * @param type the type of this new name relationship
262 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
263 * @see #getRelationsToThisName()
264 * @see #getNameRelations()
265 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
266 * @see #addNameRelationship(NameRelationship)
268 public void addRelationshipToName(TaxonNameBase toName
, NameRelationshipType type
, String ruleConsidered
){
269 NameRelationship rel
= new NameRelationship(toName
, this, type
, ruleConsidered
);
272 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to <i>this</i> taxon name
273 * and adds it both to the set of {@link #getRelationsToThisName() relations to <i>this</i> taxon name} and
274 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
276 * @param fromName the taxon name of the source for this new name relationship
277 * @param type the type of this new name relationship
278 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
279 * @see #getRelationsFromThisName()
280 * @see #getNameRelations()
281 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
282 * @see #addNameRelationship(NameRelationship)
284 public void addRelationshipFromName(TaxonNameBase fromName
, NameRelationshipType type
, String ruleConsidered
){
285 NameRelationship rel
= new NameRelationship(this, fromName
, type
, ruleConsidered
);
288 * Adds an existing {@link NameRelationship name relationship} either to the set of
289 * {@link #getRelationsToThisName() relations to <i>this</i> taxon name} or to the set of
290 * {@link #getRelationsFromThisName() relations from <i>this</i> taxon name}. If neither the
291 * source nor the target of the name relationship match with <i>this</i> taxon name
292 * no addition will be carried out.
294 * @param rel the name relationship to be added to one of <i>this</i> taxon name's name relationships sets
295 * @see #getNameRelations()
296 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
297 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
299 protected void addNameRelationship(NameRelationship rel
) {
300 if (rel
!=null && rel
.getToName().equals(this)){
301 this.relationsToThisName
.add(rel
);
302 }else if(rel
!=null && rel
.getFromName().equals(this)){
303 this.relationsFromThisName
.add(rel
);
305 //TODO: raise error???
309 * Removes one {@link NameRelationship name relationship} from one of both sets of
310 * {@link #getNameRelations() name relationships} in which <i>this</i> taxon name is involved.
311 * The name relationship will also be removed from one of both sets belonging
312 * to the second taxon name involved. Furthermore the fromName and toName
313 * attributes of the name relationship object will be nullified.
315 * @param nameRelation the name relationship which should be deleted from one of both sets
316 * @see #getNameRelations()
318 public void removeNameRelationship(NameRelationship nameRelation
) {
319 //TODO to be implemented?
320 logger
.warn("not yet fully implemented?");
321 this.relationsToThisName
.remove(nameRelation
);
322 this.relationsFromThisName
.remove(nameRelation
);
327 * Does exactly the same as the addNameRelationship method provided that
328 * the given relationship is a name relationship.
330 * @param relation the relationship to be added to one of <i>this</i> taxon name's name relationships sets
331 * @see #addNameRelationship(NameRelationship)
332 * @see #getNameRelations()
333 * @see NameRelationship
334 * @see common.RelationshipBase
336 public void addRelationship(RelationshipBase relation
) {
337 if (relation
instanceof NameRelationship
){
338 addNameRelationship((NameRelationship
)relation
);
339 if (relation
.getType() != null &&
340 ( relation
.getType().equals(NameRelationshipType
.BASIONYM()) ||
341 relation
.getType().equals(NameRelationshipType
.REPLACED_SYNONYM())
343 TaxonNameBase fromName
= ((NameRelationship
)relation
).getFromName();
344 TaxonNameBase toName
= ((NameRelationship
)relation
).getToName();
345 fromName
.getHomotypicalGroup().merge(toName
.getHomotypicalGroup());
348 logger
.warn("Relationship not of type NameRelationship!");
349 //TODO exception handling
355 * Returns the set of all {@link NameRelationship name relationships}
356 * in which <i>this</i> taxon name is involved as a source.
358 * @see #getNameRelations()
359 * @see #getRelationsToThisName()
360 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
362 @OneToMany(mappedBy
="relatedFrom", fetch
= FetchType
.LAZY
)
363 @Cascade({CascadeType
.SAVE_UPDATE
})
364 public Set
<NameRelationship
> getRelationsFromThisName() {
365 return relationsFromThisName
;
367 private void setRelationsFromThisName(Set
<NameRelationship
> relationsFromThisName
) {
368 this.relationsFromThisName
= relationsFromThisName
;
372 * Returns the set of all {@link NameRelationship name relationships}
373 * in which <i>this</i> taxon name is involved as a target.
375 * @see #getNameRelations()
376 * @see #getRelationsFromThisName()
377 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
379 @OneToMany(mappedBy
="relatedTo", fetch
= FetchType
.LAZY
)
380 @Cascade({CascadeType
.SAVE_UPDATE
})
381 public Set
<NameRelationship
> getRelationsToThisName() {
382 return relationsToThisName
;
384 private void setRelationsToThisName(Set
<NameRelationship
> relationsToThisName
) {
385 this.relationsToThisName
= relationsToThisName
;
390 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
391 * to <i>this</i> taxon name according to its corresponding nomenclature code.
392 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
393 * and the nomenclatural code rule considered.
395 * @see NomenclaturalStatus
396 * @see NomenclaturalStatusType
398 @OneToMany(fetch
= FetchType
.LAZY
)
399 @Cascade({CascadeType
.SAVE_UPDATE
})
400 public Set
<NomenclaturalStatus
> getStatus() {
406 protected void setStatus(Set
<NomenclaturalStatus
> nomStatus
) {
407 this.status
= nomStatus
;
410 * Adds a new {@link NomenclaturalStatus nomenclatural status}
411 * to <i>this</i> taxon name's set of nomenclatural status.
413 * @param nomStatus the nomenclatural status to be added
416 public void addStatus(NomenclaturalStatus nomStatus
) {
417 this.status
.add(nomStatus
);
420 * Removes one element from the set of nomenclatural status of <i>this</i> taxon name.
421 * Type and ruleConsidered attributes of the nomenclatural status object
424 * @param nomStatus the nomenclatural status of <i>this</i> taxon name which should be deleted
427 public void removeStatus(NomenclaturalStatus nomStatus
) {
428 //TODO to be implemented?
429 logger
.warn("not yet fully implemented?");
430 this.status
.remove(nomStatus
);
435 * Indicates whether <i>this</i> taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
436 * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
437 * of any other taxon name. Returns "true", if a basionym or a replaced
438 * synonym relationship from <i>this</i> taxon name to another taxon name exists,
439 * false otherwise (also in case <i>this</i> taxon name is the only one in the
440 * homotypical group).
443 public boolean isOriginalCombination(){
444 Set
<NameRelationship
> relationsFromThisName
= this.getRelationsFromThisName();
445 for (NameRelationship relation
: relationsFromThisName
) {
446 if (relation
.getType().equals(NameRelationshipType
.BASIONYM()) ||
447 relation
.getType().equals(NameRelationshipType
.REPLACED_SYNONYM())) {
455 * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of <i>this</i> taxon name.
456 * The basionym of a taxon name is its epithet-bringing synonym.
457 * For instance Pinus abies L. was published by Linnaeus and the botanist
458 * Karsten transferred later <i>this</i> taxon to the genus Picea. Therefore,
459 * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
462 public T
getBasionym(){
463 //TODO: pick the right name relationships...
464 logger
.warn("get Basionym not yet implemented");
468 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of <i>this</i> taxon name.
469 * The basionym relationship will be added to <i>this</i> taxon name
470 * and to the basionym. The basionym cannot have itself a basionym.
471 * The homotypical group of <i>this</i> taxon name will be changed the basionyms homotypical group.
472 * @see #getBasionym()
473 * @see #addBasionym(TaxonNameBase, String)
475 public void addBasionym(T basionym
){
476 addBasionym(basionym
, null);
479 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of <i>this</i> taxon name
480 * and keeps the nomenclatural rule considered for it. The basionym
481 * relationship will be added to <i>this</i> taxon name and to the basionym.
482 * The basionym cannot have itself as a basionym.
483 * The homotypical group of <i>this</i> taxon name will be changed the basionyms homotypical group.
484 * @see #getBasionym()
485 * @see #setBasionym(TaxonNameBase)
487 public void addBasionym(T basionym
, String ruleConsidered
){
488 if (basionym
!= null){
489 basionym
.addRelationshipToName(this, NameRelationshipType
.BASIONYM(), ruleConsidered
);
493 public void removeBasionym(){
495 logger
.warn("not yet implemented");
501 public abstract S
getCacheStrategy();
502 public abstract void setCacheStrategy(S cacheStrategy
);
505 * Returns the taxonomic {@link Rank rank} of <i>this</i> taxon name.
510 //@Cascade({CascadeType.SAVE_UPDATE})
511 public Rank
getRank(){
517 public void setRank(Rank rank
){
522 * Returns the {@link reference.INomenclaturalReference nomenclatural reference} of <i>this</i> taxon name.
523 * The nomenclatural reference is here meant to be the one publication
524 * <i>this</i> taxon name was originally published in while fulfilling the formal
525 * requirements as specified by the corresponding {@link NomenclaturalCode nomenclatural code}.
527 * @see reference.INomenclaturalReference
528 * @see reference.ReferenceBase
531 @Cascade({CascadeType
.SAVE_UPDATE
})
532 @Target(ReferenceBase
.class)
533 public INomenclaturalReference
getNomenclaturalReference(){
534 return this.nomenclaturalReference
;
537 * Assigns a nomenclatural {@link reference.INomenclaturalReference nomenclatural reference} to <i>this</i> taxon name.
538 * The corresponding {@link reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
539 * as it is obviously used for nomenclatural purposes.
541 * @see #getNomenclaturalReference()
543 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference
){
544 this.nomenclaturalReference
= nomenclaturalReference
;
548 * Returns the appended phrase string assigned to <i>this</i> taxon name.
549 * The appended phrase is a non-atomised addition to a name. It is
550 * not ruled by a nomenclatural code.
552 public String
getAppendedPhrase(){
553 return this.appendedPhrase
;
556 * @see #getAppendedPhrase()
558 public void setAppendedPhrase(String appendedPhrase
){
559 this.appendedPhrase
= appendedPhrase
;
563 * Returns the details string of the nomenclatural reference assigned
564 * to <i>this</i> taxon name. The details describe the exact localisation within
565 * the publication used as nomenclature reference. These are mostly
566 * (implicitly) pages but can also be figures or tables or any other
567 * element of a publication. A nomenclatural micro reference (details)
568 * requires the existence of a nomenclatural reference.
570 //Details of the nomenclatural reference (protologue).
571 public String
getNomenclaturalMicroReference(){
572 return this.nomenclaturalMicroReference
;
575 * @see #getNomenclaturalMicroReference()
577 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference
){
578 this.nomenclaturalMicroReference
= nomenclaturalMicroReference
;
582 * Returns the boolean value of the flag indicating whether the used {@link eu.etaxonomy.cdm.strategy.parser.INonViralNameParser parser}
583 * method was able to parse the taxon name string successfully (false)
584 * or not (true). The parser itself may also depend on the {@link NomenclaturalCode nomenclatural code}
585 * governing the construction of <i>this</i> taxon name.
587 * @return the boolean value of the hasProblem flag
588 * @see #getNameCache()
590 public boolean getHasProblem(){
591 return this.hasProblem
;
594 * @see #getHasProblem()
596 public void setHasProblem(boolean hasProblem
){
597 this.hasProblem
= hasProblem
;
600 * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.
602 * @see #getHasProblem()
604 public boolean hasProblem(){
605 return getHasProblem();
610 //*********************** TYPE DESIGNATION *********************************************//
615 * Returns the set of {@link TypeDesignationBase type designations} assigned
616 * to <i>this</i> taxon name.
617 * @see NameTypeDesignation
618 * @see SpecimenTypeDesignation
621 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
622 @Cascade(CascadeType
.SAVE_UPDATE
)
623 public Set
<TypeDesignationBase
> getTypeDesignations() {
624 return typeDesignations
;
628 * @see #getNameTypeDesignations()
630 private void setTypeDesignations(Set
<TypeDesignationBase
> typeDesignations
) {
631 this.typeDesignations
= typeDesignations
;
635 * Removes one element from the set of {@link TypeDesignationBase type designations} assigned to the
636 * {@link HomotypicalGroup homotypical group} to which <i>this</i> taxon name belongs.
637 * The type designation itself will be nullified.
639 * @param typeDesignation the type designation which should be deleted
640 * @see #removeSpecimenTypeDesignation(SpecimenTypeDesignation)
641 * @see #removeNameTypeDesignation(NameTypeDesignation)
643 public void removeTypeDesignation(TypeDesignationBase typeDesignation
) {
644 logger
.warn("not yet fully implemented: nullify the specimen type designation itself?");
645 this.typeDesignations
.remove(typeDesignation
);
650 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} assigned
651 * indirectly to <i>this</i> taxon name through its {@link HomotypicalGroup homotypical group}.
652 * The rank of <i>this</i> taxon name is generally "species" or below.
653 * The specimen type designations include all the specimens on which
654 * the typification of this name is based (and which are common to all
655 * taxon names belonging to the homotypical group) and eventually
656 * the status of these designations.
658 * @see SpecimenTypeDesignation
659 * @see NameTypeDesignation
662 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignationsOfHomotypicalGroup() {
663 return this.getHomotypicalGroup().getSpecimenTypeDesignations();
666 //*********************** NAME TYPE DESIGNATION *********************************************//
669 * Returns the set of {@link NameTypeDesignation name type designations} assigned
670 * to <i>this</i> taxon name the rank of which must be above "species".
671 * The name type designations include all the taxon names used to typify
672 * this name and eventually the rejected or conserved status
673 * of these designations.
675 * @see NameTypeDesignation
676 * @see SpecimenTypeDesignation
679 public Set
<NameTypeDesignation
> getNameTypeDesignations() {
680 Set
<NameTypeDesignation
> result
= new HashSet
<NameTypeDesignation
>();
681 for (TypeDesignationBase typeDesignation
: this.typeDesignations
){
682 if (typeDesignation
instanceof NameTypeDesignation
){
683 result
.add((NameTypeDesignation
)typeDesignation
);
690 * Creates and adds a new {@link NameTypeDesignation name type designation}
691 * to <i>this</i> taxon name's set of name type designations.
693 * @param typeSpecies the taxon name to be used as type of <i>this</i> taxon name
694 * @param citation the reference for this new designation
695 * @param citationMicroReference the string with the details (generally pages) within the reference
696 * @param originalNameString the taxon name string used in the reference to assert this designation
697 * @param isRejectedType the boolean status for rejected
698 * @param isConservedType the boolean status for conserved
699 * @param isLectoType the boolean status for isLectotype
700 * @param lectoCitation the reference for the lectotype
701 * @param lectoMicroCitation the String for the micro citation of a lectotype
702 * @param addToAllHomotypicNames boolean, if true the name type designation is added to all names of the homotypical
703 * group this taxon name belongs to
704 * @see #getNameTypeDesignations()
705 * @see #addTypeDesignation(Specimen, TypeDesignationStatus, ReferenceBase, String, String)
707 public void addNameTypeDesignation(TaxonNameBase typeSpecies
,
708 ReferenceBase citation
,
709 String citationMicroReference
,
710 String originalNameString
,
711 boolean isRejectedType
,
712 boolean isConservedType
,
714 boolean isNotDesignated
,
715 boolean addToAllHomotypicNames
) {
716 NameTypeDesignation nameTypeDesignation
= new NameTypeDesignation(typeSpecies
, citation
, citationMicroReference
, originalNameString
, isRejectedType
, isConservedType
, isNotDesignated
);
717 addTypeDesignation(nameTypeDesignation
, addToAllHomotypicNames
);
720 //*********************** SPECIMEN TYPE DESIGNATION *********************************************//
723 * Returns the set of {@link SpecimenTypeDesignation specimen type designations}
724 * that typify <i>this</i> taxon name.
727 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignations() {
728 Set
<SpecimenTypeDesignation
> result
= new HashSet
<SpecimenTypeDesignation
>();
729 for (TypeDesignationBase typeDesignation
: this.typeDesignations
){
730 if (typeDesignation
instanceof SpecimenTypeDesignation
){
731 result
.add((SpecimenTypeDesignation
)typeDesignation
);
739 * Adds a new {@link SpecimenTypeDesignation specimen type designation}
740 * (using its attributes as parameters) to the set of specimen type designations assigned to the
741 * {@link HomotypicalGroup homotypical group} to which <i>this</i> taxon name belongs.
743 * @param typeSpecimen the specimen to be used as a type for <i>this</i> taxon name's homotypical group
744 * @param status the specimen type designation status
745 * @param citation the reference for this new specimen type designation
746 * @param citationMicroReference the string with the details (generally pages) within the reference
747 * @param originalNameString the taxon name used in the reference to assert this designation
748 * @param addToAllHomotypicNames boolean, if true the name type designation is added to all names of the homotypical
749 * group this taxon name belongs to
750 * @see HomotypicalGroup#getSpecimenTypeDesignations()
751 * @see #addTypeDesignation(TaxonNameBase, ReferenceBase, String, String, boolean, boolean)
752 * @see TypeDesignationStatus
754 public void addSpecimenTypeDesignation(Specimen typeSpecimen
,
755 TypeDesignationStatus status
,
756 ReferenceBase citation
,
757 String citationMicroReference
,
758 String originalNameString
,
759 boolean addToAllHomotypicNames
) {
760 SpecimenTypeDesignation specimenTypeDesignation
= new SpecimenTypeDesignation(typeSpecimen
, status
, citation
, citationMicroReference
, originalNameString
);
761 addTypeDesignation(specimenTypeDesignation
, addToAllHomotypicNames
);
764 private boolean addTypeDesignation(TypeDesignationBase typeDesignation
, boolean addToAllNames
){
765 //at them moment typeDesignations are not persisted with the homotypical group
766 //so explicit adding to the homotypical group is not necessary.
767 if (typeDesignation
!= null){
768 this.typeDesignations
.add(typeDesignation
);
769 typeDesignation
.addTypifiedName(this);
772 for (TaxonNameBase taxonName
: this.getHomotypicalGroup().getTypifiedNames()){
773 if (taxonName
!= this){
774 taxonName
.addTypeDesignation(typeDesignation
, false);
784 //*********************** HOMOTYPICAL GROUP *********************************************//
788 * Returns the {@link HomotypicalGroup homotypical group} to which
789 * <i>this</i> taxon name belongs. A homotypical group represents all taxon names
790 * that share the same type specimens.
792 * @see HomotypicalGroup
795 @Cascade({CascadeType
.SAVE_UPDATE
})
796 public HomotypicalGroup
getHomotypicalGroup() {
797 return homotypicalGroup
;
799 @Deprecated //only for bidirectional and persistence use
800 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup
) {
801 this.homotypicalGroup
= newHomotypicalGroup
;
804 // *************************************************************************//
807 * @see #getNomenclaturalReference()
810 public StrictReferenceBase
getCitation(){
811 //TODO What is the purpose of this method differing from the getNomenclaturalReference method?
812 logger
.warn("getCitation not yet implemented");
817 * Returns the complete string containing the
818 * {@link reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
819 * (including {@link #getNomenclaturalMicroReference() details}) assigned to <i>this</i> taxon name.
821 * @return the string containing the nomenclatural reference of <i>this</i> taxon name
822 * @see reference.INomenclaturalReference#getNomenclaturalCitation()
823 * @see #getNomenclaturalReference()
824 * @see #getNomenclaturalMicroReference()
827 public String
getCitationString(){
828 logger
.warn("getCitationString not yet implemented");
833 public String
[] getProblems(){
834 logger
.warn("getProblems not yet implemented");
839 * Returns the string containing the publication date (generally only year)
840 * of the nomenclatural reference for <i>this</i> taxon name, null if there is
841 * no nomenclatural reference.
843 * @return the string containing the publication date of <i>this</i> taxon name
844 * @see reference.INomenclaturalReference#getYear()
847 public String
getReferenceYear(){
848 if (this.getNomenclaturalReference() != null ){
849 return this.getNomenclaturalReference().getYear();
856 * Returns the set of {@link taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
857 * In this context a taxon base means the use of a taxon name by a reference
858 * either as a taxon ("accepted/correct" name) or as a (junior) synonym.
859 * A taxon name can be used by several distinct references but only once
860 * within a taxonomic treatment (identified by one reference).
862 * @see taxon.TaxonBase
864 * @see #getSynonyms()
866 @OneToMany(mappedBy
="name", fetch
= FetchType
.LAZY
)
867 public Set
<TaxonBase
> getTaxonBases() {
868 return this.taxonBases
;
871 * @see #getTaxonBases()
873 protected void setTaxonBases(Set
<TaxonBase
> taxonBases
) {
874 if (taxonBases
== null){
875 taxonBases
= new HashSet
<TaxonBase
>();
877 this.taxonBases
= taxonBases
;
881 * Adds a new {@link taxon.TaxonBase taxon base}
882 * to the set of taxon bases using <i>this</i> taxon name.
884 * @param taxonBase the taxon base to be added
885 * @see #getTaxonBases()
886 * @see #removeTaxonBase(TaxonBase)
889 public void addTaxonBase(TaxonBase taxonBase
){
890 taxonBases
.add(taxonBase
);
892 invokeSetMethod(methodTaxonBaseSetName
, taxonBase
);
895 * Removes one element from the set of {@link taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
897 * @param taxonBase the taxon base which should be removed from the corresponding set
898 * @see #addTaxonBase(TaxonBase)
900 public void removeTaxonBase(TaxonBase taxonBase
){
901 taxonBases
.remove(taxonBase
);
903 invokeSetMethodWithNull(methodTaxonBaseSetName
, taxonBase
);
906 private void initMethods(){
907 if (methodTaxonBaseSetName
== null){
909 methodTaxonBaseSetName
= TaxonBase
.class.getDeclaredMethod("setName", TaxonNameBase
.class);
910 methodTaxonBaseSetName
.setAccessible(true);
911 } catch (Exception e
) {
913 //TODO handle exception
916 if (methodDescriptionSetTaxonName
== null){
918 methodDescriptionSetTaxonName
= TaxonNameDescription
.class.getDeclaredMethod("setTaxonName", TaxonNameBase
.class);
919 methodDescriptionSetTaxonName
.setAccessible(true);
920 } catch (Exception e
) {
922 //TODO handle exception
930 * Returns the set of {@link taxon.Taxon taxa} ("accepted/correct" names according to any
931 * reference) that are based on <i>this</i> taxon name. This set is a subset of
932 * the set returned by getTaxonBases().
935 * @see #getTaxonBases()
936 * @see #getSynonyms()
939 public Set
<Taxon
> getTaxa(){
940 Set
<Taxon
> result
= new HashSet
<Taxon
>();
941 for (TaxonBase taxonBase
: this.taxonBases
){
942 if (taxonBase
instanceof Taxon
){
943 result
.add((Taxon
)taxonBase
);
950 * Returns the set of {@link taxon.Synonym (junior) synonyms} (according to any
951 * reference) that are based on <i>this</i> taxon name. This set is a subset of
952 * the set returned by getTaxonBases().
955 * @see #getTaxonBases()
959 public Set
<Synonym
> getSynonyms() {
960 Set
<Synonym
> result
= new HashSet
<Synonym
>();
961 for (TaxonBase taxonBase
: this.taxonBases
){
962 if (taxonBase
instanceof Synonym
){
963 result
.add((Synonym
)taxonBase
);
970 // *********** DESCRIPTIONS *************************************
973 * Returns the set of {@link description.TaxonNameDescription taxon name descriptions} assigned
974 * to <i>this</i> taxon name. A taxon name description is a piece of information
975 * concerning the taxon name like for instance the content of its first
976 * publication (protolog) or a picture of this publication.
978 * @see #addDescription(TaxonNameDescription)
979 * @see #removeDescription(TaxonNameDescription)
980 * @see description.TaxonNameDescription
982 @OneToMany(mappedBy
="taxonName", fetch
= FetchType
.LAZY
)
983 @Cascade({CascadeType
.SAVE_UPDATE
})
984 public Set
<TaxonNameDescription
> getDescriptions() {
988 * @see #getDescriptions()
990 protected void setDescriptions(Set
<TaxonNameDescription
> descriptions
) {
991 this.descriptions
= descriptions
;
994 * Adds a new {@link description.TaxonNameDescription taxon name description}
995 * to the set of taxon name descriptions assigned to <i>this</i> taxon name. The
996 * content of the {@link description.TaxonNameDescription#getTaxonName() taxonName attribute} of the
997 * taxon name description itself will be replaced with <i>this</i> taxon name.
999 * @param description the taxon name description to be added
1000 * @see #getDescriptions()
1001 * @see #removeDescription(TaxonNameDescription)
1003 public void addDescription(TaxonNameDescription description
) {
1005 this.invokeSetMethod(methodDescriptionSetTaxonName
, description
);
1006 descriptions
.add(description
);
1009 * Removes one element from the set of {@link description.TaxonNameDescription taxon name descriptions} assigned
1010 * to <i>this</i> taxon name. The content of the {@link description.TaxonNameDescription#getTaxonName() taxonName attribute}
1011 * of the description itself will be set to "null".
1013 * @param description the taxon name description which should be removed
1014 * @see #getDescriptions()
1015 * @see #addDescription(TaxonNameDescription)
1016 * @see description.TaxonNameDescription#getTaxonName()
1018 public void removeDescription(TaxonNameDescription description
) {
1020 this.invokeSetMethod(methodDescriptionSetTaxonName
, null);
1021 descriptions
.remove(description
);
1031 * Returns the boolean value indicating whether a given taxon name belongs
1032 * to the same {@link HomotypicalGroup homotypical group} as <i>this</i> taxon name (true)
1033 * or not (false). Returns "true" only if the homotypical groups of both
1034 * taxon names exist and if they are identical.
1036 * @param homoTypicName the taxon name the homotypical group of which is to be checked
1037 * @return the boolean value of the check
1038 * @see HomotypicalGroup
1040 public boolean isHomotypic(TaxonNameBase homoTypicName
) {
1041 if (homoTypicName
== null) {
1044 HomotypicalGroup homotypicGroup
= homoTypicName
.getHomotypicalGroup();
1045 if (homotypicGroup
== null || this.getHomotypicalGroup() == null) {
1048 if (homotypicGroup
.equals(this.getHomotypicalGroup())) {
1056 //********* Rank comparison shortcuts ********************//
1058 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1059 * taxon name is higher than the genus rank (true) or not (false).
1060 * Suprageneric non viral names are monomials.
1061 * Returns false if rank is null.
1064 * @see #isInfraGeneric()
1066 * @see #isInfraSpecific()
1069 public boolean isSupraGeneric() {
1073 return getRank().isSupraGeneric();
1076 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1077 * taxon name is the genus rank (true) or not (false). Non viral names with
1078 * genus rank are monomials. Returns false if rank is null.
1080 * @see #isSupraGeneric()
1081 * @see #isInfraGeneric()
1083 * @see #isInfraSpecific()
1086 public boolean isGenus() {
1090 return getRank().isGenus();
1093 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1094 * taxon name is higher than the species rank and lower than the
1095 * genus rank (true) or not (false). Infrageneric non viral names are
1096 * binomials. Returns false if rank is null.
1098 * @see #isSupraGeneric()
1101 * @see #isInfraSpecific()
1104 public boolean isInfraGeneric() {
1108 return getRank().isInfraGeneric();
1111 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1112 * taxon name is the species rank (true) or not (false). Non viral names
1113 * with species rank are binomials.
1114 * Returns false if rank is null.
1116 * @see #isSupraGeneric()
1118 * @see #isInfraGeneric()
1119 * @see #isInfraSpecific()
1122 public boolean isSpecies() {
1126 return getRank().isSpecies();
1129 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1130 * taxon name is lower than the species rank (true) or not (false).
1131 * Infraspecific non viral names are trinomials.
1132 * Returns false if rank is null.
1134 * @see #isSupraGeneric()
1136 * @see #isInfraGeneric()
1140 public boolean isInfraSpecific() {
1144 return getRank().isInfraSpecific();
1149 * Returns null as the {@link NomenclaturalCode nomenclatural code} that governs
1150 * the construction of <i>this</i> taxon name since there is no specific
1151 * nomenclatural code defined. The real implementention takes place in the
1152 * subclasses {@link ViralName ViralName}, {@link BacterialName BacterialName},
1153 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName} and
1154 * {@link ZoologicalName ZoologicalName}. Each taxon name is governed by one
1155 * and only one nomenclatural code.
1158 * @see #isCodeCompliant()
1159 * @see #getHasProblem()
1162 abstract public NomenclaturalCode
getNomenclaturalCode();
1164 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1167 * Generates and returns the string with the scientific name of <i>this</i>
1168 * taxon name (only non viral taxon names can be generated from their
1169 * components). This string may be stored in the inherited
1170 * {@link common.IdentifiableEntity#getTitleCache() titleCache} attribute.
1171 * This method overrides the generic and inherited
1172 * IdentifiableEntity#generateTitle() method.
1174 * @return the string with the composed name of this non viral taxon name with authorship (and maybe year)
1175 * @see common.IdentifiableEntity#generateTitle()
1176 * @see common.IdentifiableEntity#getTitleCache()
1179 public String
generateTitle() {
1180 // TODO Auto-generated method stub
1181 logger
.warn("not yet implemented");