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
.Column
;
17 import javax
.persistence
.Entity
;
18 import javax
.persistence
.FetchType
;
19 import javax
.persistence
.Inheritance
;
20 import javax
.persistence
.InheritanceType
;
21 import javax
.persistence
.ManyToMany
;
22 import javax
.persistence
.ManyToOne
;
23 import javax
.persistence
.OneToMany
;
24 import javax
.persistence
.Transient
;
25 import javax
.xml
.bind
.annotation
.XmlAccessType
;
26 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
27 import javax
.xml
.bind
.annotation
.XmlAnyElement
;
28 import javax
.xml
.bind
.annotation
.XmlAttribute
;
29 import javax
.xml
.bind
.annotation
.XmlElement
;
30 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
31 import javax
.xml
.bind
.annotation
.XmlIDREF
;
32 import javax
.xml
.bind
.annotation
.XmlRootElement
;
33 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
34 import javax
.xml
.bind
.annotation
.XmlTransient
;
35 import javax
.xml
.bind
.annotation
.XmlType
;
37 import org
.apache
.log4j
.Logger
;
38 import org
.hibernate
.annotations
.Cascade
;
39 import org
.hibernate
.annotations
.CascadeType
;
40 import org
.hibernate
.annotations
.Index
;
41 import org
.hibernate
.annotations
.Table
;
42 import org
.hibernate
.annotations
.Target
;
44 import eu
.etaxonomy
.cdm
.model
.common
.IParsable
;
45 import eu
.etaxonomy
.cdm
.model
.common
.IReferencedEntity
;
46 import eu
.etaxonomy
.cdm
.model
.common
.IRelated
;
47 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
48 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
49 import eu
.etaxonomy
.cdm
.model
.description
.TaxonNameDescription
;
50 import eu
.etaxonomy
.cdm
.model
.occurrence
.Specimen
;
51 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
52 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
53 import eu
.etaxonomy
.cdm
.model
.reference
.StrictReferenceBase
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
57 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.INameCacheStrategy
;
60 * The upmost (abstract) class for scientific taxon names regardless of any
61 * particular {@link NomenclaturalCode nomenclature code}. The scientific taxon name does not depend
62 * on the use made of it in a publication or a treatment
63 * ({@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon concept respectively potential taxon})
64 * as an {@link eu.etaxonomy.cdm.model.taxon.Taxon "accepted" respectively "correct" (taxon) name}
65 * or as a {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
67 * This class corresponds partially to: <ul>
68 * <li> TaxonName according to the TDWG ontology
69 * <li> ScientificName and CanonicalName according to the TCS
70 * <li> ScientificName according to the ABCD schema
75 * @created 08-Nov-2007 13:06:57
77 @XmlAccessorType(XmlAccessType
.FIELD
)
78 @XmlType(name
= "TaxonNameBase", propOrder
= {
80 "nomenclaturalMicroReference",
81 "nomenclaturalReference",
84 "protectedFullTitleCache",
87 "relationsFromThisName",
88 "relationsToThisName",
93 @XmlRootElement(name
= "TaxonNameBase")
95 @Inheritance(strategy
=InheritanceType
.SINGLE_TABLE
)
96 @Table(appliesTo
="TaxonNameBase", indexes
= { @Index(name
= "taxonNameBaseTitleCacheIndex", columnNames
= { "persistentTitleCache" }) })
97 public abstract class TaxonNameBase
<T
extends TaxonNameBase
, S
extends INameCacheStrategy
> extends IdentifiableEntity
<TaxonNameBase
> implements IReferencedEntity
, IParsable
, IRelated
{
99 static Logger logger
= Logger
.getLogger(TaxonNameBase
.class);
101 private static Method methodDescriptionSetTaxonName
;
103 @XmlElement(name
= "FullTitleCache")
104 private String fullTitleCache
;
106 //if true titleCache will not be automatically generated/updated
107 @XmlElement(name
= "ProtectedFullTitleCache")
108 private boolean protectedFullTitleCache
;
110 @XmlElementWrapper(name
= "Descriptions")
111 @XmlElement(name
= "Description")
112 private Set
<TaxonNameDescription
> descriptions
= new HashSet
<TaxonNameDescription
>();
114 @XmlElement(name
= "AppendedPhrase")
115 private String appendedPhrase
;
117 @XmlElement(name
= "NomenclaturalMicroReference")
118 private String nomenclaturalMicroReference
;
121 private boolean hasProblem
= false;
123 @XmlElementWrapper(name
= "TypeDesignations")
124 @XmlElement(name
= "TypeDesignation")
126 @XmlSchemaType(name
= "IDREF")
127 private Set
<TypeDesignationBase
> typeDesignations
= new HashSet
<TypeDesignationBase
>();
129 @XmlElement(name
= "HomotypicalGroup")
131 @XmlSchemaType(name
= "IDREF")
132 private HomotypicalGroup homotypicalGroup
= new HomotypicalGroup();
134 @XmlElementWrapper(name
= "RelationsFromThisName")
135 @XmlElement(name
= "RelationFromThisName")
137 @XmlSchemaType(name
= "IDREF")
138 private Set
<NameRelationship
> relationsFromThisName
= new HashSet
<NameRelationship
>();
140 @XmlElementWrapper(name
= "RelationsToThisName")
141 @XmlElement(name
= "RelationToThisName")
143 @XmlSchemaType(name
= "IDREF")
144 private Set
<NameRelationship
> relationsToThisName
= new HashSet
<NameRelationship
>();
146 @XmlElementWrapper(name
= "NomenclaturalStatus_")
147 @XmlElement(name
= "NomenclaturalStatus")
149 @XmlSchemaType(name
= "IDREF")
150 private Set
<NomenclaturalStatus
> status
= new HashSet
<NomenclaturalStatus
>();
153 //@XmlElementWrapper(name = "TaxonBases")
154 //@XmlElement(name = "TaxonBase")
155 private Set
<TaxonBase
> taxonBases
= new HashSet
<TaxonBase
>();
159 @XmlElement(name
= "Rank")
161 @XmlSchemaType(name
= "IDREF")
164 // FIXME: This must be an IDREF to the corresponding nomenclatural reference.
167 @XmlElement(name
= "NomenclaturalReference", type
= ReferenceBase
.class)
169 @XmlSchemaType(name
= "IDREF")
170 private INomenclaturalReference nomenclaturalReference
;
172 static Method methodTaxonBaseSetName
;
174 // ************* CONSTRUCTORS *************/
176 * Class constructor: creates a new empty taxon name.
178 * @see #TaxonNameBase(Rank)
179 * @see #TaxonNameBase(HomotypicalGroup)
180 * @see #TaxonNameBase(Rank, HomotypicalGroup)
182 public TaxonNameBase() {
186 * Class constructor: creates a new taxon name
187 * only containing its {@link Rank rank}.
189 * @param rank the rank to be assigned to <i>this</i> taxon name
190 * @see #TaxonNameBase()
191 * @see #TaxonNameBase(HomotypicalGroup)
192 * @see #TaxonNameBase(Rank, HomotypicalGroup)
194 public TaxonNameBase(Rank rank
) {
198 * Class constructor: creates a new taxon name
199 * only containing its {@link HomotypicalGroup homotypical group}.
200 * The new taxon name will be also added to the set of taxon names
201 * belonging to this homotypical group.
203 * @param homotypicalGroup the homotypical group to which <i>this</i> taxon name belongs
204 * @see #TaxonNameBase()
205 * @see #TaxonNameBase(Rank)
206 * @see #TaxonNameBase(Rank, HomotypicalGroup)
208 public TaxonNameBase(HomotypicalGroup homotypicalGroup
) {
209 this(null, homotypicalGroup
);
212 * Class constructor: creates a new taxon name
213 * only containing its {@link Rank rank} and
214 * its {@link HomotypicalGroup homotypical group}.
215 * The new taxon name will be also added to the set of taxon names
216 * belonging to this homotypical group.
218 * @param rank the rank to be assigned to <i>this</i> taxon name
219 * @param homotypicalGroup the homotypical group to which <i>this</i> taxon name belongs
220 * @see #TaxonNameBase()
221 * @see #TaxonNameBase(Rank)
222 * @see #TaxonNameBase(HomotypicalGroup)
224 public TaxonNameBase(Rank rank
, HomotypicalGroup homotypicalGroup
) {
227 if (homotypicalGroup
== null){
228 homotypicalGroup
= new HomotypicalGroup();
230 homotypicalGroup
.addTypifiedName(this);
233 //********* METHODS **************************************/
235 //@Index(name="TaxonNameBaseTitleCacheIndex")
236 // public String getTitleCache(){
237 // return super.getTitleCache();
241 * Returns the boolean value "false" since the components of <i>this</i> taxon name
242 * cannot follow the rules of a corresponding {@link NomenclaturalCode nomenclatural code}
243 * which is not defined for this class. The nomenclature code depends on
244 * the concrete name subclass ({@link BacterialName BacterialName},
245 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
246 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName})
247 * to which a taxon name belongs.
252 public abstract boolean isCodeCompliant();
254 public abstract String
generateFullTitle();
257 public String
getFullTitleCache(){
258 if (protectedFullTitleCache
){
259 return this.fullTitleCache
;
261 if (fullTitleCache
== null){
262 this.setFullTitleCache(generateFullTitle(), protectedFullTitleCache
);
264 return fullTitleCache
;
267 public void setFullTitleCache(String fullTitleCache
){
268 setFullTitleCache(fullTitleCache
, PROTECTED
);
271 public void setFullTitleCache(String fullTitleCache
, boolean protectCache
){
272 //TODO truncation of full title cache
273 if (fullTitleCache
!= null && fullTitleCache
.length() > 329){
274 logger
.warn("Truncation of full title cache: " + this.toString() + "/" + fullTitleCache
);
275 fullTitleCache
= fullTitleCache
.substring(0, 329) + "...";
277 this.fullTitleCache
= fullTitleCache
;
278 this.setProtectedFullTitleCache(protectCache
);
282 @Deprecated //for hibernate use only
283 protected String
getPersistentFullTitleCache(){
284 return getFullTitleCache();
287 @Deprecated //for hibernate use only
288 protected void setPersistentFullTitleCache(String fullTitleCache
){
289 this.fullTitleCache
= fullTitleCache
;
292 public boolean isProtectedFullTitleCache() {
293 return protectedFullTitleCache
;
296 public void setProtectedFullTitleCache(boolean protectedFullTitleCache
) {
297 this.protectedFullTitleCache
= protectedFullTitleCache
;
301 * Returns the set of all {@link NameRelationship name relationships}
302 * in which <i>this</i> taxon name is involved. A taxon name can be both source
303 * in some name relationships or target in some others.
305 * @see #getRelationsToThisName()
306 * @see #getRelationsFromThisName()
307 * @see #addNameRelationship(NameRelationship)
308 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
309 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
312 public Set
<NameRelationship
> getNameRelations() {
313 Set
<NameRelationship
> rels
= new HashSet
<NameRelationship
>();
314 rels
.addAll(getRelationsFromThisName());
315 rels
.addAll(getRelationsToThisName());
319 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from <i>this</i> taxon name to another taxon name
320 * and adds it both to the set of {@link #getRelationsFromThisName() relations from <i>this</i> taxon name} and
321 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
323 * @param toName the taxon name of the target for this new name relationship
324 * @param type the type of this new name relationship
325 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
326 * @see #getRelationsToThisName()
327 * @see #getNameRelations()
328 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
329 * @see #addNameRelationship(NameRelationship)
331 public void addRelationshipToName(TaxonNameBase toName
, NameRelationshipType type
, String ruleConsidered
){
332 NameRelationship rel
= new NameRelationship(toName
, this, type
, ruleConsidered
);
335 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to <i>this</i> taxon name
336 * and adds it both to the set of {@link #getRelationsToThisName() relations to <i>this</i> taxon name} and
337 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
339 * @param fromName the taxon name of the source for this new name relationship
340 * @param type the type of this new name relationship
341 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
342 * @see #getRelationsFromThisName()
343 * @see #getNameRelations()
344 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
345 * @see #addNameRelationship(NameRelationship)
347 public void addRelationshipFromName(TaxonNameBase fromName
, NameRelationshipType type
, String ruleConsidered
){
348 NameRelationship rel
= new NameRelationship(this, fromName
, type
, ruleConsidered
);
351 * Adds an existing {@link NameRelationship name relationship} either to the set of
352 * {@link #getRelationsToThisName() relations to <i>this</i> taxon name} or to the set of
353 * {@link #getRelationsFromThisName() relations from <i>this</i> taxon name}. If neither the
354 * source nor the target of the name relationship match with <i>this</i> taxon name
355 * no addition will be carried out.
357 * @param rel the name relationship to be added to one of <i>this</i> taxon name's name relationships sets
358 * @see #getNameRelations()
359 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
360 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
362 protected void addNameRelationship(NameRelationship rel
) {
363 if (rel
!=null && rel
.getToName().equals(this)){
364 this.relationsToThisName
.add(rel
);
365 }else if(rel
!=null && rel
.getFromName().equals(this)){
366 this.relationsFromThisName
.add(rel
);
368 //TODO: raise error???
372 * Removes one {@link NameRelationship name relationship} from one of both sets of
373 * {@link #getNameRelations() name relationships} in which <i>this</i> taxon name is involved.
374 * The name relationship will also be removed from one of both sets belonging
375 * to the second taxon name involved. Furthermore the fromName and toName
376 * attributes of the name relationship object will be nullified.
378 * @param nameRelation the name relationship which should be deleted from one of both sets
379 * @see #getNameRelations()
381 public void removeNameRelationship(NameRelationship nameRelation
) {
382 //TODO to be implemented?
383 logger
.warn("not yet fully implemented?");
384 this.relationsToThisName
.remove(nameRelation
);
385 this.relationsFromThisName
.remove(nameRelation
);
390 * Does exactly the same as the addNameRelationship method provided that
391 * the given relationship is a name relationship.
393 * @param relation the relationship to be added to one of <i>this</i> taxon name's name relationships sets
394 * @see #addNameRelationship(NameRelationship)
395 * @see #getNameRelations()
396 * @see NameRelationship
397 * @see eu.etaxonomy.cdm.model.common.RelationshipBase
399 public void addRelationship(RelationshipBase relation
) {
400 if (relation
instanceof NameRelationship
){
401 addNameRelationship((NameRelationship
)relation
);
402 if (relation
.getType() != null &&
403 ( relation
.getType().equals(NameRelationshipType
.BASIONYM()) ||
404 relation
.getType().equals(NameRelationshipType
.REPLACED_SYNONYM())
406 TaxonNameBase fromName
= ((NameRelationship
)relation
).getFromName();
407 TaxonNameBase toName
= ((NameRelationship
)relation
).getToName();
408 fromName
.getHomotypicalGroup().merge(toName
.getHomotypicalGroup());
411 logger
.warn("Relationship not of type NameRelationship!");
412 //TODO exception handling
418 * Returns the set of all {@link NameRelationship name relationships}
419 * in which <i>this</i> taxon name is involved as a source.
421 * @see #getNameRelations()
422 * @see #getRelationsToThisName()
423 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
425 @OneToMany(mappedBy
="relatedFrom", fetch
= FetchType
.LAZY
)
426 @Cascade({CascadeType
.SAVE_UPDATE
})
427 public Set
<NameRelationship
> getRelationsFromThisName() {
428 return relationsFromThisName
;
430 private void setRelationsFromThisName(Set
<NameRelationship
> relationsFromThisName
) {
431 this.relationsFromThisName
= relationsFromThisName
;
435 * Returns the set of all {@link NameRelationship name relationships}
436 * in which <i>this</i> taxon name is involved as a target.
438 * @see #getNameRelations()
439 * @see #getRelationsFromThisName()
440 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
442 @OneToMany(mappedBy
="relatedTo", fetch
= FetchType
.LAZY
)
443 @Cascade({CascadeType
.SAVE_UPDATE
})
444 public Set
<NameRelationship
> getRelationsToThisName() {
445 return relationsToThisName
;
447 private void setRelationsToThisName(Set
<NameRelationship
> relationsToThisName
) {
448 this.relationsToThisName
= relationsToThisName
;
453 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
454 * to <i>this</i> taxon name according to its corresponding nomenclature code.
455 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
456 * and the nomenclatural code rule considered.
458 * @see NomenclaturalStatus
459 * @see NomenclaturalStatusType
461 @OneToMany(fetch
= FetchType
.LAZY
)
462 @Cascade({CascadeType
.SAVE_UPDATE
})
463 public Set
<NomenclaturalStatus
> getStatus() {
469 protected void setStatus(Set
<NomenclaturalStatus
> nomStatus
) {
470 this.status
= nomStatus
;
473 * Adds a new {@link NomenclaturalStatus nomenclatural status}
474 * to <i>this</i> taxon name's set of nomenclatural status.
476 * @param nomStatus the nomenclatural status to be added
479 public void addStatus(NomenclaturalStatus nomStatus
) {
480 this.status
.add(nomStatus
);
483 * Removes one element from the set of nomenclatural status of <i>this</i> taxon name.
484 * Type and ruleConsidered attributes of the nomenclatural status object
487 * @param nomStatus the nomenclatural status of <i>this</i> taxon name which should be deleted
490 public void removeStatus(NomenclaturalStatus nomStatus
) {
491 //TODO to be implemented?
492 logger
.warn("not yet fully implemented?");
493 this.status
.remove(nomStatus
);
498 * Indicates whether <i>this</i> taxon name is a {@link NameRelationshipType#BASIONYM() basionym}
499 * or a {@link NameRelationshipType#REPLACED_SYNONYM() replaced synonym}
500 * of any other taxon name. Returns "true", if a basionym or a replaced
501 * synonym {@link NameRelationship relationship} from <i>this</i> taxon name to another taxon name exists,
502 * false otherwise (also in case <i>this</i> taxon name is the only one in the
503 * homotypical group).
506 public boolean isOriginalCombination(){
507 Set
<NameRelationship
> relationsFromThisName
= this.getRelationsFromThisName();
508 for (NameRelationship relation
: relationsFromThisName
) {
509 if (relation
.getType().equals(NameRelationshipType
.BASIONYM()) ||
510 relation
.getType().equals(NameRelationshipType
.REPLACED_SYNONYM())) {
518 * Returns the taxon name which is the {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
519 * The basionym of a taxon name is its epithet-bringing synonym.
520 * For instance <i>Pinus abies</i> L. was published by Linnaeus and the botanist
521 * Karsten transferred later <i>this</i> taxon to the genus Picea. Therefore,
522 * <i>Pinus abies</i> L. is the basionym of the new combination <i>Picea abies</i> (L.) H. Karst.
525 public T
getBasionym(){
526 //TODO: pick the right name relationships...
527 logger
.warn("get Basionym not yet implemented");
531 * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name.
532 * The basionym {@link NameRelationship relationship} will be added to <i>this</i> taxon name
533 * and to the basionym. The basionym cannot have itself a basionym.
534 * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
535 * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
537 * @param basionym the taxon name to be set as the basionym of <i>this</i> taxon name
538 * @see #getBasionym()
539 * @see #addBasionym(TaxonNameBase, String)
541 public void addBasionym(T basionym
){
542 addBasionym(basionym
, null);
545 * Assigns a taxon name as {@link NameRelationshipType#BASIONYM() basionym} of <i>this</i> taxon name
546 * and keeps the nomenclatural rule considered for it. The basionym
547 * {@link NameRelationship relationship} will be added to <i>this</i> taxon name and to the basionym.
548 * The basionym cannot have itself a basionym.
549 * The {@link HomotypicalGroup homotypical groups} of <i>this</i> taxon name and of the basionym
550 * will be {@link HomotypicalGroup#merge(HomotypicalGroup) merged}.
552 * @param basionym the taxon name to be set as the basionym of <i>this</i> taxon name
553 * @param ruleConsidered the string identifying the nomenclatural rule
554 * @see #getBasionym()
555 * @see #addBasionym(TaxonNameBase)
557 public void addBasionym(T basionym
, String ruleConsidered
){
558 if (basionym
!= null){
559 basionym
.addRelationshipToName(this, NameRelationshipType
.BASIONYM(), ruleConsidered
);
564 * Removes the {@link NameRelationshipType#BASIONYM() basionym} {@link NameRelationship relationship} from the set of
565 * {@link #getRelationsToThisName() name relationships to} <i>this</i> taxon name. The same relationhip will be
566 * removed from the set of {@link #getRelationsFromThisName() name relationships from} the taxon name
567 * previously used as basionym.
569 * @see #getBasionym()
570 * @see #addBasionym(TaxonNameBase)
572 public void removeBasionym(){
574 logger
.warn("not yet implemented");
580 * Returns the {@link eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy cache strategy} used to generate
581 * several strings corresponding to <i>this</i> taxon name
582 * (in particular taxon name caches and author strings).
584 * @return the cache strategy used for <i>this</i> taxon name
585 * @see eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy
586 * @see eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy
589 public abstract S
getCacheStrategy();
591 * @see #getCacheStrategy()
593 public abstract void setCacheStrategy(S cacheStrategy
);
596 * Returns the taxonomic {@link Rank rank} of <i>this</i> taxon name.
601 //@Cascade({CascadeType.SAVE_UPDATE})
602 public Rank
getRank(){
608 public void setRank(Rank rank
){
613 * Returns the {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} of <i>this</i> taxon name.
614 * The nomenclatural reference is here meant to be the one publication
615 * <i>this</i> taxon name was originally published in while fulfilling the formal
616 * requirements as specified by the corresponding {@link NomenclaturalCode nomenclatural code}.
618 * @see eu.etaxonomy.cdm.model.reference.INomenclaturalReference
619 * @see eu.etaxonomy.cdm.model.reference.ReferenceBase
622 @Cascade({CascadeType
.SAVE_UPDATE
})
623 @Target(ReferenceBase
.class)
624 public INomenclaturalReference
getNomenclaturalReference(){
625 return this.nomenclaturalReference
;
628 * Assigns a {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference nomenclatural reference} to <i>this</i> taxon name.
629 * The corresponding {@link eu.etaxonomy.cdm.model.reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
630 * as it is obviously used for nomenclatural purposes.
632 * @see #getNomenclaturalReference()
634 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference
){
635 this.nomenclaturalReference
= nomenclaturalReference
;
639 * Returns the appended phrase string assigned to <i>this</i> taxon name.
640 * The appended phrase is a non-atomised addition to a name. It is
641 * not ruled by a nomenclatural code.
643 public String
getAppendedPhrase(){
644 return this.appendedPhrase
;
647 * @see #getAppendedPhrase()
649 public void setAppendedPhrase(String appendedPhrase
){
650 this.appendedPhrase
= appendedPhrase
;
654 * Returns the details string of the {@link #getNomenclaturalReference() nomenclatural reference} assigned
655 * to <i>this</i> taxon name. The details describe the exact localisation within
656 * the publication used as nomenclature reference. These are mostly
657 * (implicitly) pages but can also be figures or tables or any other
658 * element of a publication. A nomenclatural micro reference (details)
659 * requires the existence of a nomenclatural reference.
661 //Details of the nomenclatural reference (protologue).
662 public String
getNomenclaturalMicroReference(){
663 return this.nomenclaturalMicroReference
;
666 * @see #getNomenclaturalMicroReference()
668 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference
){
669 this.nomenclaturalMicroReference
= nomenclaturalMicroReference
;
673 * Returns the boolean value of the flag indicating whether the used {@link eu.etaxonomy.cdm.strategy.parser.INonViralNameParser parser}
674 * method was able to parse the taxon name string successfully (false)
675 * or not (true). The parser itself may also depend on the {@link NomenclaturalCode nomenclatural code}
676 * governing the construction of <i>this</i> taxon name.
678 * @return the boolean value of the hasProblem flag
680 public boolean getHasProblem(){
681 return this.hasProblem
;
684 * @see #getHasProblem()
686 public void setHasProblem(boolean hasProblem
){
687 this.hasProblem
= hasProblem
;
690 * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.
692 * @see #getHasProblem()
694 public boolean hasProblem(){
695 return getHasProblem();
700 //*********************** TYPE DESIGNATION *********************************************//
705 * Returns the set of {@link TypeDesignationBase type designations} assigned
706 * to <i>this</i> taxon name.
707 * @see NameTypeDesignation
708 * @see SpecimenTypeDesignation
711 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
712 @Cascade(CascadeType
.SAVE_UPDATE
)
713 public Set
<TypeDesignationBase
> getTypeDesignations() {
714 return typeDesignations
;
718 * @see #getNameTypeDesignations()
720 private void setTypeDesignations(Set
<TypeDesignationBase
> typeDesignations
) {
721 this.typeDesignations
= typeDesignations
;
725 * Removes one element from the set of {@link TypeDesignationBase type designations} assigned to
726 * <i>this</i> taxon name. The type designation itself will be nullified.
728 * @param typeDesignation the type designation which should be deleted
730 public void removeTypeDesignation(TypeDesignationBase typeDesignation
) {
731 logger
.warn("not yet fully implemented: nullify the specimen type designation itself?");
732 this.typeDesignations
.remove(typeDesignation
);
737 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} assigned
738 * to <i>this</i> taxon name. The {@link Rank rank} of <i>this</i> taxon name is generally
739 * "species" or below. The specimen type designations include all the
740 * specimens on which the typification of this name is based (which are
741 * exclusively used to typify taxon names belonging to the same
742 * {@link HomotypicalGroup homotypical group} to which <i>this</i> taxon name
743 * belongs) and eventually the status of these designations.
745 * @see SpecimenTypeDesignation
746 * @see NameTypeDesignation
747 * @see HomotypicalGroup
750 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignationsOfHomotypicalGroup() {
751 return this.getHomotypicalGroup().getSpecimenTypeDesignations();
754 //*********************** NAME TYPE DESIGNATION *********************************************//
757 * Returns the set of {@link NameTypeDesignation name type designations} assigned
758 * to <i>this</i> taxon name the rank of which must be above "species".
759 * The name type designations include all the taxon names used to typify
760 * <i>this</i> taxon name and eventually the rejected or conserved status
761 * of these designations.
763 * @see NameTypeDesignation
764 * @see SpecimenTypeDesignation
767 public Set
<NameTypeDesignation
> getNameTypeDesignations() {
768 Set
<NameTypeDesignation
> result
= new HashSet
<NameTypeDesignation
>();
769 for (TypeDesignationBase typeDesignation
: this.typeDesignations
){
770 if (typeDesignation
instanceof NameTypeDesignation
){
771 result
.add((NameTypeDesignation
)typeDesignation
);
778 * Creates and adds a new {@link NameTypeDesignation name type designation}
779 * to <i>this</i> taxon name's set of type designations.
781 * @param typeSpecies the taxon name to be used as type of <i>this</i> taxon name
782 * @param citation the reference for this new designation
783 * @param citationMicroReference the string with the details (generally pages) within the reference
784 * @param originalNameString the taxon name string used in the reference to assert this designation
785 * @param isRejectedType the boolean status for a rejected name type designation
786 * @param isConservedType the boolean status for a conserved name type designation
787 * @param isLectoType the boolean status for a lectotype name type designation
788 * @param isNotDesignated the boolean status for a name type designation without name type
789 * @param addToAllHomotypicNames the boolean indicating whether the name type designation should be
790 * added to all taxon names of the homotypical group this taxon name belongs to
791 * @see #getNameTypeDesignations()
792 * @see NameTypeDesignation
793 * @see TypeDesignationBase#isNotDesignated()
795 public void addNameTypeDesignation(TaxonNameBase typeSpecies
,
796 ReferenceBase citation
,
797 String citationMicroReference
,
798 String originalNameString
,
799 boolean isRejectedType
,
800 boolean isConservedType
,
802 boolean isNotDesignated
,
803 boolean addToAllHomotypicNames
) {
804 NameTypeDesignation nameTypeDesignation
= new NameTypeDesignation(typeSpecies
, citation
, citationMicroReference
, originalNameString
, isRejectedType
, isConservedType
, isNotDesignated
);
805 addTypeDesignation(nameTypeDesignation
, addToAllHomotypicNames
);
808 //*********************** SPECIMEN TYPE DESIGNATION *********************************************//
811 * Returns the set of {@link SpecimenTypeDesignation specimen type designations}
812 * that typify <i>this</i> taxon name.
815 public Set
<SpecimenTypeDesignation
> getSpecimenTypeDesignations() {
816 Set
<SpecimenTypeDesignation
> result
= new HashSet
<SpecimenTypeDesignation
>();
817 for (TypeDesignationBase typeDesignation
: this.typeDesignations
){
818 if (typeDesignation
instanceof SpecimenTypeDesignation
){
819 result
.add((SpecimenTypeDesignation
)typeDesignation
);
827 * Creates and adds a new {@link SpecimenTypeDesignation specimen type designation}
828 * to <i>this</i> taxon name's set of type designations.
830 * @param typeSpecimen the specimen to be used as a type for <i>this</i> taxon name
831 * @param status the specimen type designation status
832 * @param citation the reference for this new specimen type designation
833 * @param citationMicroReference the string with the details (generally pages) within the reference
834 * @param originalNameString the taxon name used in the reference to assert this designation
835 * @param isNotDesignated the boolean status for a specimen type designation without specimen type
836 * @param addToAllHomotypicNames the boolean indicating whether the specimen type designation should be
837 * added to all taxon names of the homotypical group the typified
838 * taxon name belongs to
839 * @see #getSpecimenTypeDesignations()
840 * @see TypeDesignationStatus
841 * @see SpecimenTypeDesignation
842 * @see TypeDesignationBase#isNotDesignated()
844 public void addSpecimenTypeDesignation(Specimen typeSpecimen
,
845 TypeDesignationStatus status
,
846 ReferenceBase citation
,
847 String citationMicroReference
,
848 String originalNameString
,
849 boolean isNotDesignated
,
850 boolean addToAllHomotypicNames
) {
851 SpecimenTypeDesignation specimenTypeDesignation
= new SpecimenTypeDesignation(typeSpecimen
, status
, citation
, citationMicroReference
, originalNameString
, isNotDesignated
);
852 addTypeDesignation(specimenTypeDesignation
, addToAllHomotypicNames
);
855 private boolean addTypeDesignation(TypeDesignationBase typeDesignation
, boolean addToAllNames
){
856 //at them moment typeDesignations are not persisted with the homotypical group
857 //so explicit adding to the homotypical group is not necessary.
858 if (typeDesignation
!= null){
859 this.typeDesignations
.add(typeDesignation
);
860 typeDesignation
.addTypifiedName(this);
863 for (TaxonNameBase taxonName
: this.getHomotypicalGroup().getTypifiedNames()){
864 if (taxonName
!= this){
865 taxonName
.addTypeDesignation(typeDesignation
, false);
875 //*********************** HOMOTYPICAL GROUP *********************************************//
879 * Returns the {@link HomotypicalGroup homotypical group} to which
880 * <i>this</i> taxon name belongs. A homotypical group represents all taxon names
881 * that share the same types.
883 * @see HomotypicalGroup
886 @Cascade({CascadeType
.SAVE_UPDATE
})
887 public HomotypicalGroup
getHomotypicalGroup() {
888 return homotypicalGroup
;
890 @Deprecated //only for bidirectional and persistence use
891 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup
) {
892 this.homotypicalGroup
= newHomotypicalGroup
;
895 // *************************************************************************//
898 * @see #getNomenclaturalReference()
901 public StrictReferenceBase
getCitation(){
902 //TODO What is the purpose of this method differing from the getNomenclaturalReference method?
903 logger
.warn("getCitation not yet implemented");
908 * Returns the complete string containing the
909 * {@link eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation() nomenclatural reference citation}
910 * and the {@link #getNomenclaturalMicroReference() details} assigned to <i>this</i> taxon name.
912 * @return the string containing the nomenclatural reference of <i>this</i> taxon name
913 * @see eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getNomenclaturalCitation()
914 * @see #getNomenclaturalReference()
915 * @see #getNomenclaturalMicroReference()
918 public String
getCitationString(){
919 logger
.warn("getCitationString not yet implemented");
924 * Not yet implemented
927 public String
[] getProblems(){
928 logger
.warn("getProblems not yet implemented");
933 * Returns the string containing the publication date (generally only year)
934 * of the {@link #getNomenclaturalReference() nomenclatural reference} for <i>this</i> taxon name, null if there is
935 * no nomenclatural reference.
937 * @return the string containing the publication date of <i>this</i> taxon name
938 * @see eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getYear()
941 public String
getReferenceYear(){
942 if (this.getNomenclaturalReference() != null ){
943 return this.getNomenclaturalReference().getYear();
950 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
951 * In this context a taxon base means the use of a taxon name by a reference
952 * either as a {@link eu.etaxonomy.cdm.model.taxon.Taxon taxon} ("accepted/correct" name) or
953 * as a (junior) {@link eu.etaxonomy.cdm.model.taxon.Synonym synonym}.
954 * A taxon name can be used by several distinct {@link eu.etaxonomy.cdm.model.reference.ReferenceBase references} but only once
955 * within a taxonomic treatment (identified by one reference).
958 * @see #getSynonyms()
960 @OneToMany(mappedBy
="name", fetch
= FetchType
.LAZY
)
961 public Set
<TaxonBase
> getTaxonBases() {
962 return this.taxonBases
;
965 * @see #getTaxonBases()
967 protected void setTaxonBases(Set
<TaxonBase
> taxonBases
) {
968 if (taxonBases
== null){
969 taxonBases
= new HashSet
<TaxonBase
>();
971 this.taxonBases
= taxonBases
;
975 * Adds a new {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon base}
976 * to the set of taxon bases using <i>this</i> taxon name.
978 * @param taxonBase the taxon base to be added
979 * @see #getTaxonBases()
980 * @see #removeTaxonBase(TaxonBase)
983 public void addTaxonBase(TaxonBase taxonBase
){
984 taxonBases
.add(taxonBase
);
986 invokeSetMethod(methodTaxonBaseSetName
, taxonBase
);
989 * Removes one element from the set of {@link eu.etaxonomy.cdm.model.taxon.TaxonBase taxon bases} that refer to <i>this</i> taxon name.
991 * @param taxonBase the taxon base which should be removed from the corresponding set
992 * @see #getTaxonBases()
993 * @see #addTaxonBase(TaxonBase)
995 public void removeTaxonBase(TaxonBase taxonBase
){
996 taxonBases
.remove(taxonBase
);
998 invokeSetMethodWithNull(methodTaxonBaseSetName
, taxonBase
);
1001 private void initMethods(){
1002 if (methodTaxonBaseSetName
== null){
1004 methodTaxonBaseSetName
= TaxonBase
.class.getDeclaredMethod("setName", TaxonNameBase
.class);
1005 methodTaxonBaseSetName
.setAccessible(true);
1006 } catch (Exception e
) {
1007 e
.printStackTrace();
1008 //TODO handle exception
1011 if (methodDescriptionSetTaxonName
== null){
1013 methodDescriptionSetTaxonName
= TaxonNameDescription
.class.getDeclaredMethod("setTaxonName", TaxonNameBase
.class);
1014 methodDescriptionSetTaxonName
.setAccessible(true);
1015 } catch (Exception e
) {
1016 e
.printStackTrace();
1017 //TODO handle exception
1025 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Taxon taxa} ("accepted/correct" names according to any
1026 * reference) that are based on <i>this</i> taxon name. This set is a subset of
1027 * the set returned by getTaxonBases().
1029 * @see eu.etaxonomy.cdm.model.taxon.Taxon
1030 * @see #getTaxonBases()
1031 * @see #getSynonyms()
1034 public Set
<Taxon
> getTaxa(){
1035 Set
<Taxon
> result
= new HashSet
<Taxon
>();
1036 for (TaxonBase taxonBase
: this.taxonBases
){
1037 if (taxonBase
instanceof Taxon
){
1038 result
.add((Taxon
)taxonBase
);
1045 * Returns the set of {@link eu.etaxonomy.cdm.model.taxon.Synonym (junior) synonyms} (according to any
1046 * reference) that are based on <i>this</i> taxon name. This set is a subset of
1047 * the set returned by getTaxonBases().
1049 * @see eu.etaxonomy.cdm.model.taxon.Synonym
1050 * @see #getTaxonBases()
1054 public Set
<Synonym
> getSynonyms() {
1055 Set
<Synonym
> result
= new HashSet
<Synonym
>();
1056 for (TaxonBase taxonBase
: this.taxonBases
){
1057 if (taxonBase
instanceof Synonym
){
1058 result
.add((Synonym
)taxonBase
);
1065 // *********** DESCRIPTIONS *************************************
1068 * Returns the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
1069 * to <i>this</i> taxon name. A taxon name description is a piece of information
1070 * concerning the taxon name like for instance the content of its first
1071 * publication (protolog) or a picture of this publication.
1073 * @see #addDescription(TaxonNameDescription)
1074 * @see #removeDescription(TaxonNameDescription)
1075 * @see eu.etaxonomy.cdm.model.description.TaxonNameDescription
1077 @OneToMany(mappedBy
="taxonName", fetch
= FetchType
.LAZY
)
1078 @Cascade({CascadeType
.SAVE_UPDATE
})
1079 public Set
<TaxonNameDescription
> getDescriptions() {
1080 return descriptions
;
1083 * @see #getDescriptions()
1085 protected void setDescriptions(Set
<TaxonNameDescription
> descriptions
) {
1086 this.descriptions
= descriptions
;
1089 * Adds a new {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name description}
1090 * to the set of taxon name descriptions assigned to <i>this</i> taxon name. The
1091 * content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute} of the
1092 * taxon name description itself will be replaced with <i>this</i> taxon name.
1094 * @param description the taxon name description to be added
1095 * @see #getDescriptions()
1096 * @see #removeDescription(TaxonNameDescription)
1098 public void addDescription(TaxonNameDescription description
) {
1100 this.invokeSetMethod(methodDescriptionSetTaxonName
, description
);
1101 descriptions
.add(description
);
1104 * Removes one element from the set of {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription taxon name descriptions} assigned
1105 * to <i>this</i> taxon name. The content of the {@link eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName() taxonName attribute}
1106 * of the description itself will be set to "null".
1108 * @param description the taxon name description which should be removed
1109 * @see #getDescriptions()
1110 * @see #addDescription(TaxonNameDescription)
1111 * @see eu.etaxonomy.cdm.model.description.TaxonNameDescription#getTaxonName()
1113 public void removeDescription(TaxonNameDescription description
) {
1115 this.invokeSetMethod(methodDescriptionSetTaxonName
, null);
1116 descriptions
.remove(description
);
1126 * Returns the boolean value indicating whether a given taxon name belongs
1127 * to the same {@link HomotypicalGroup homotypical group} as <i>this</i> taxon name (true)
1128 * or not (false). Returns "true" only if the homotypical groups of both
1129 * taxon names exist and if they are identical.
1131 * @param homoTypicName the taxon name the homotypical group of which is to be checked
1132 * @return the boolean value of the check
1133 * @see HomotypicalGroup
1135 public boolean isHomotypic(TaxonNameBase homoTypicName
) {
1136 if (homoTypicName
== null) {
1139 HomotypicalGroup homotypicGroup
= homoTypicName
.getHomotypicalGroup();
1140 if (homotypicGroup
== null || this.getHomotypicalGroup() == null) {
1143 if (homotypicGroup
.equals(this.getHomotypicalGroup())) {
1151 //********* Rank comparison shortcuts ********************//
1153 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1154 * taxon name is higher than the genus rank (true) or not (false).
1155 * Suprageneric non viral names are monomials.
1156 * Returns false if rank is null.
1159 * @see #isInfraGeneric()
1161 * @see #isInfraSpecific()
1164 public boolean isSupraGeneric() {
1168 return getRank().isSupraGeneric();
1171 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1172 * taxon name is the genus rank (true) or not (false). Non viral names with
1173 * genus rank are monomials. Returns false if rank is null.
1175 * @see #isSupraGeneric()
1176 * @see #isInfraGeneric()
1178 * @see #isInfraSpecific()
1181 public boolean isGenus() {
1185 return getRank().isGenus();
1188 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1189 * taxon name is higher than the species rank and lower than the
1190 * genus rank (true) or not (false). Infrageneric non viral names are
1191 * binomials. Returns false if rank is null.
1193 * @see #isSupraGeneric()
1196 * @see #isInfraSpecific()
1199 public boolean isInfraGeneric() {
1203 return getRank().isInfraGeneric();
1206 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1207 * taxon name is the species rank (true) or not (false). Non viral names
1208 * with species rank are binomials.
1209 * Returns false if rank is null.
1211 * @see #isSupraGeneric()
1213 * @see #isInfraGeneric()
1214 * @see #isInfraSpecific()
1217 public boolean isSpecies() {
1221 return getRank().isSpecies();
1224 * Returns the boolean value indicating whether the taxonomic {@link Rank rank} of <i>this</i>
1225 * taxon name is lower than the species rank (true) or not (false).
1226 * Infraspecific non viral names are trinomials.
1227 * Returns false if rank is null.
1229 * @see #isSupraGeneric()
1231 * @see #isInfraGeneric()
1235 public boolean isInfraSpecific() {
1239 return getRank().isInfraSpecific();
1244 * Returns null as the {@link NomenclaturalCode nomenclatural code} that governs
1245 * the construction of <i>this</i> taxon name since there is no specific
1246 * nomenclatural code defined. The real implementention takes place in the
1247 * subclasses {@link ViralName ViralName}, {@link BacterialName BacterialName},
1248 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName} and
1249 * {@link ZoologicalName ZoologicalName}. Each taxon name is governed by one
1250 * and only one nomenclatural code.
1253 * @see #isCodeCompliant()
1254 * @see #getHasProblem()
1257 abstract public NomenclaturalCode
getNomenclaturalCode();
1259 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1262 * Generates and returns the string with the scientific name of <i>this</i>
1263 * taxon name (only non viral taxon names can be generated from their
1264 * components). This string may be stored in the inherited
1265 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
1266 * This method overrides the generic and inherited
1267 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle() method} from
1268 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
1270 * @return the string with the composed name of this non viral taxon name with authorship (and maybe year)
1271 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1272 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
1275 public String
generateTitle() {
1276 // TODO Auto-generated method stub
1277 logger
.warn("not yet implemented");