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
;
13 import java
.util
.HashSet
;
16 import javax
.persistence
.Entity
;
17 import javax
.persistence
.OneToMany
;
18 import javax
.persistence
.Transient
;
19 import javax
.xml
.bind
.annotation
.XmlAccessType
;
20 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
21 import javax
.xml
.bind
.annotation
.XmlElement
;
22 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
23 import javax
.xml
.bind
.annotation
.XmlRootElement
;
24 import javax
.xml
.bind
.annotation
.XmlType
;
26 import org
.apache
.log4j
.Logger
;
27 import org
.hibernate
.annotations
.Cascade
;
28 import org
.hibernate
.annotations
.CascadeType
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.TeamOrPersonBase
;
31 import eu
.etaxonomy
.cdm
.model
.common
.RelationshipBase
;
32 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
33 import eu
.etaxonomy
.cdm
.strategy
.cache
.name
.BotanicNameDefaultCacheStrategy
;
34 import eu
.etaxonomy
.cdm
.strategy
.parser
.INonViralNameParser
;
35 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImpl
;
38 * The taxon name class for plants and fungi.
42 * @created 08-Nov-2007 13:06:15
44 @XmlAccessorType(XmlAccessType
.FIELD
)
45 @XmlType(name
= "", propOrder
= {
53 @XmlRootElement(name
= "BotanicalName")
55 public class BotanicalName
extends NonViralName
{
57 private static final Logger logger
= Logger
.getLogger(BotanicalName
.class);
59 //if set: this name is a hybrid formula (a hybrid that does not have an own name) and no other hybrid flags may be set. A
60 //hybrid name may not have either an authorteam nor other name components.
61 @XmlElement(name
="IsHybridFormula")
62 private boolean isHybridFormula
= false;
64 @XmlElement(name
="IsMonomHybrid")
65 private boolean isMonomHybrid
= false;
67 @XmlElement(name
="IsBinomHybrid")
68 private boolean isBinomHybrid
= false;
70 @XmlElement(name
="IsTrinomHybrid")
71 private boolean isTrinomHybrid
= false;
73 //Only for fungi: to indicate that the type of the name is asexual or not
74 @XmlElement(name
="IsAnamorphic")
75 private boolean isAnamorphic
;
77 @XmlElementWrapper(name
= "HybridRelationships")
78 @XmlElement(name
= "HybridRelationship")
79 private Set
<HybridRelationship
> hybridRelationships
= new HashSet();
81 static private INonViralNameParser nameParser
= new NonViralNameParserImpl();
83 // ************* CONSTRUCTORS *************/
86 * Class constructor: creates a new botanical taxon name instance
87 * only containing the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
89 * @see #BotanicalName(Rank, HomotypicalGroup)
90 * @see #BotanicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
91 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
93 protected BotanicalName(){
95 this.cacheStrategy
= BotanicNameDefaultCacheStrategy
.NewInstance();
98 * Class constructor: creates a new botanical taxon name instance
99 * only containing its {@link common.Rank rank},
100 * its {@link common.HomotypicalGroup homotypical group} and
101 * the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
102 * The new botanical taxon name instance will be also added to the set of
103 * botanical taxon names belonging to this homotypical group.
105 * @param rank the rank to be assigned to this botanical taxon name
106 * @param homotypicalGroup the homotypical group to which this botanical taxon name belongs
107 * @see #BotanicalName()
108 * @see #BotanicalName(Rank, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
109 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
111 protected BotanicalName(Rank rank
, HomotypicalGroup homotypicalGroup
) {
112 super(rank
, homotypicalGroup
);
113 this.cacheStrategy
= BotanicNameDefaultCacheStrategy
.NewInstance();
116 * Class constructor: creates a new botanical taxon name instance
117 * containing its {@link common.Rank rank},
118 * its {@link common.HomotypicalGroup homotypical group},
119 * its scientific name components, its {@link agent.TeamOrPersonBase author(team)},
120 * its {@link reference.INomenclaturalReference nomenclatural reference} and
121 * the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
122 * The new botanical taxon name instance will be also added to the set of
123 * botanical taxon names belonging to this homotypical group.
125 * @param rank the rank to be assigned to this botanical taxon name
126 * @param genusOrUninomial the string for this botanical taxon name
127 * if its rank is genus or higher or for the genus part
128 * if its rank is lower than genus
129 * @param infraGenericEpithet the string for the first epithet of
130 * this botanical taxon name if its rank is lower than genus
131 * and higher than species aggregate
132 * @param specificEpithet the string for the first epithet of
133 * this botanical taxon name if its rank is species aggregate or lower
134 * @param infraSpecificEpithet the string for the second epithet of
135 * this botanical taxon name if its rank is lower than species
136 * @param combinationAuthorTeam the author or the team who published this botanical taxon name
137 * @param nomenclaturalReference the nomenclatural reference where this botanical taxon name was published
138 * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
139 * @param homotypicalGroup the homotypical group to which this botanical taxon name belongs
140 * @see #BotanicalName()
141 * @see #BotanicalName(Rank, HomotypicalGroup)
142 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
143 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
144 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy
145 * @see eu.etaxonomy.cdm.strategy.cache.IIdentifiableEntityCacheStrategy
147 protected BotanicalName(Rank rank
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, TeamOrPersonBase combinationAuthorTeam
, INomenclaturalReference nomenclaturalReference
, String nomenclMicroRef
, HomotypicalGroup homotypicalGroup
) {
148 super(rank
, genusOrUninomial
, infraGenericEpithet
, specificEpithet
, infraSpecificEpithet
, combinationAuthorTeam
, nomenclaturalReference
, nomenclMicroRef
, homotypicalGroup
);
149 this.cacheStrategy
= BotanicNameDefaultCacheStrategy
.NewInstance();
153 //********* METHODS **************************************/
156 * Creates a new botanical taxon name instance
157 * only containing its {@link common.Rank rank} and
158 * the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
160 * @param rank the rank to be assigned to this botanical taxon name
161 * @see #BotanicalName(Rank, HomotypicalGroup)
162 * @see #NewInstance(Rank, HomotypicalGroup)
163 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
164 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
166 public static BotanicalName
NewInstance(Rank rank
){
167 return new BotanicalName(rank
, null);
170 * Creates a new botanical taxon name instance
171 * only containing its {@link common.Rank rank},
172 * its {@link common.HomotypicalGroup homotypical group} and
173 * the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
174 * The new botanical taxon name instance will be also added to the set of
175 * botanical taxon names belonging to this homotypical group.
177 * @param rank the rank to be assigned to this botanical taxon name
178 * @param homotypicalGroup the homotypical group to which this botanical taxon name belongs
179 * @see #NewInstance(Rank)
180 * @see #NewInstance(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
181 * @see #BotanicalName(Rank, HomotypicalGroup)
182 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
184 public static BotanicalName
NewInstance(Rank rank
, HomotypicalGroup homotypicalGroup
){
185 return new BotanicalName(rank
, homotypicalGroup
);
188 * Creates a new botanical taxon name instance
189 * containing its {@link common.Rank rank},
190 * its {@link common.HomotypicalGroup homotypical group},
191 * its scientific name components, its {@link agent.TeamOrPersonBase author(team)},
192 * its {@link reference.INomenclaturalReference nomenclatural reference} and
193 * the {@link eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy default cache strategy}.
194 * The new botanical taxon name instance will be also added to the set of
195 * botanical taxon names belonging to this homotypical group.
197 * @param rank the rank to be assigned to this botanical taxon name
198 * @param genusOrUninomial the string for this botanical taxon name
199 * if its rank is genus or higher or for the genus part
200 * if its rank is lower than genus
201 * @param infraGenericEpithet the string for the first epithet of
202 * this botanical taxon name if its rank is lower than genus
203 * and higher than species aggregate
204 * @param specificEpithet the string for the first epithet of
205 * this botanical taxon name if its rank is species aggregate or lower
206 * @param infraSpecificEpithet the string for the second epithet of
207 * this botanical taxon name if its rank is lower than species
208 * @param combinationAuthorTeam the author or the team who published this botanical taxon name
209 * @param nomenclaturalReference the nomenclatural reference where this botanical taxon name was published
210 * @param nomenclMicroRef the string with the details for precise location within the nomenclatural reference
211 * @param homotypicalGroup the homotypical group to which this botanical taxon name belongs
212 * @see #NewInstance(Rank)
213 * @see #NewInstance(Rank, HomotypicalGroup)
214 * @see #ZoologicalName(Rank, String, String, String, String, TeamOrPersonBase, INomenclaturalReference, String, HomotypicalGroup)
215 * @see eu.etaxonomy.cdm.strategy.cache.BotanicNameDefaultCacheStrategy
217 public static BotanicalName
NewInstance(Rank rank
, String genusOrUninomial
, String infraGenericEpithet
, String specificEpithet
, String infraSpecificEpithet
, TeamOrPersonBase combinationAuthorTeam
, INomenclaturalReference nomenclaturalReference
, String nomenclMicroRef
, HomotypicalGroup homotypicalGroup
) {
218 return new BotanicalName(rank
, genusOrUninomial
, infraGenericEpithet
, specificEpithet
, infraSpecificEpithet
, combinationAuthorTeam
, nomenclaturalReference
, nomenclMicroRef
, homotypicalGroup
);
222 * Returns a botanical taxon name based on parsing a string representing
223 * all elements (according to the ICBN) of a botanical taxon name (where
224 * the scientific name is an uninomial) including authorship but without
225 * nomenclatural reference.
227 * @param fullNameString the string to be parsed
228 * @return the new botanical taxon name
230 public static BotanicalName
PARSED_NAME(String fullNameString
){
231 return PARSED_NAME(fullNameString
, Rank
.GENUS());
235 * Returns a botanical taxon name based on parsing a string representing
236 * all elements (according to the ICBN) of a botanical taxon name including
237 * authorship but without nomenclatural reference. The parsing result
238 * depends on the given rank of the botanical taxon name to be created.
240 * @param fullNameString the string to be parsed
241 * @param rank the rank of the taxon name
242 * @return the new botanical taxon name
244 public static BotanicalName
PARSED_NAME(String fullNameString
, Rank rank
){
245 if (nameParser
== null){
246 nameParser
= new NonViralNameParserImpl();
248 return (BotanicalName
)nameParser
.parseFullName(fullNameString
, NomenclaturalCode
.ICBN(), rank
);
252 * Returns a botanical taxon name based on parsing a string representing
253 * all elements (according to the ICBN) of a botanical taxon name (where
254 * the scientific name is an uninomial) including authorship and
255 * nomenclatural reference. Eventually a new {@link reference.INomenclaturalReference nomenclatural reference}
256 * instance will also be created.
258 * @param fullNameAndReferenceString the string to be parsed
259 * @return the new botanical taxon name
261 public static BotanicalName
PARSED_REFERENCE(String fullNameAndReferenceString
){
262 return PARSED_REFERENCE(fullNameAndReferenceString
, Rank
.GENUS());
266 * Returns a botanical taxon name based on parsing a string representing
267 * all elements (according to the ICBN) of a botanical taxon name including
268 * authorship and nomenclatural reference. The parsing result depends on
269 * the given rank of the botanical taxon name to be created.
270 * Eventually a new {@link reference.INomenclaturalReference nomenclatural reference}
271 * instance will also be created.
273 * @param fullNameAndReferenceString the string to be parsed
274 * @return the new botanical taxon name
276 public static BotanicalName
PARSED_REFERENCE(String fullNameAndReferenceString
, Rank rank
){
277 if (nameParser
== null){
278 nameParser
= new NonViralNameParserImpl();
280 return (BotanicalName
)nameParser
.parseFullReference(fullNameAndReferenceString
, NomenclaturalCode
.ICBN(), rank
);
285 * Returns the set of all {@link HybridRelationship hybrid relationships}
286 * in which this botanical taxon name is involved. Any botanical taxon name
287 * (even itself a hybrid taxon name) can be a parent of another hybrid
290 * @see #getParentRelationships()
291 * @see #getChildRelationships()
292 * @see #addHybridRelationship(HybridRelationship)
293 * @see #addRelationship(RelationshipBase)
296 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.DELETE_ORPHAN
})
297 public Set
<HybridRelationship
> getHybridRelationships() {
298 return hybridRelationships
;
301 * @see #getHybridRelationships()
303 protected void setHybridRelationships(Set
<HybridRelationship
> relationships
) {
304 this.hybridRelationships
= relationships
;
307 * Adds the given {@link HybridRelationship hybrid relationship} to the set
308 * of {@link #getHybridRelationships() hybrid relationships} of both botanical taxon names
309 * involved in this hybrid relationship. One of both botanical taxon names
310 * must be this botanical taxon name else no addition will be carried out.
311 * The {@link common.RelationshipBase#getRelatedTo() child botanical taxon name}
312 * must be a hybrid, which means that one of its four hybrid flags must be set.
314 * @param relationship the hybrid relationship to be added
315 * @see #isHybridFormula()
316 * @see #isMonomHybrid()
317 * @see #isBinomHybrid()
318 * @see #isTrinomHybrid()
319 * @see #getHybridRelationships()
320 * @see #getParentRelationships()
321 * @see #getChildRelationships()
322 * @see #addRelationship(RelationshipBase)
324 public void addHybridRelationship(HybridRelationship relationship
) {
325 this.hybridRelationships
.add(relationship
);
328 * Removes one {@link HybridRelationship hybrid relationship} from the set of
329 * {@link #getHybridRelationships() hybrid relationships} in which this botanical taxon name
330 * is involved. The hybrid relationship will also be removed from the set
331 * belonging to the second botanical taxon name involved.
333 * @param relationship the hybrid relationship which should be deleted from the corresponding sets
334 * @see #getHybridRelationships()
336 public void removeHybridRelationship(HybridRelationship relationship
) {
337 this.hybridRelationships
.remove(relationship
);
341 * Returns the set of all {@link HybridRelationship hybrid relationships}
342 * in which this botanical taxon name is involved as a {@link common.RelationshipBase#getRelatedFrom() parent}.
344 * @see #getHybridRelationships()
345 * @see #getChildRelationships()
346 * @see HybridRelationshipType
349 public Set
<HybridRelationship
> getParentRelationships() {
350 // FIXME: filter relations
351 return hybridRelationships
;
354 * Returns the set of all {@link HybridRelationship hybrid relationships}
355 * in which this botanical taxon name is involved as a {@link common.RelationshipBase#getRelatedTo() child}.
357 * @see #getHybridRelationships()
358 * @see #getParentRelationships()
359 * @see HybridRelationshipType
362 public Set
<HybridRelationship
> getChildRelationships() {
363 // FIXME: filter relations
364 return hybridRelationships
;
368 * Does the same as the addHybridRelationship method if the given
369 * {@link common.RelationshipBase relation} is also a {@link HybridRelationship hybrid relationship}.
370 * Otherwise this method does the same as the overwritten {@link TaxonNameBase#addRelationship(RelationshipBase) addRelationship}
371 * method from TaxonNameBase.
373 * @param relation the relationship to be added to some of this taxon name's relationships sets
374 * @see #addHybridRelationship(HybridRelationship)
375 * @see TaxonNameBase#addRelationship(RelationshipBase)
376 * @see TaxonNameBase#addNameRelationship(NameRelationship)
378 public void addRelationship(RelationshipBase relation
) {
379 if (relation
instanceof HybridRelationship
){
380 addHybridRelationship((HybridRelationship
)relation
);
382 super.addRelationship(relation
);
387 * Returns the boolean value of the flag indicating whether the name of this
388 * botanical taxon name is a hybrid formula (true) or not (false). A hybrid
389 * named by a hybrid formula (composed with its parent names by placing the
390 * multiplication sign between them) does not have an own published name
391 * and therefore has neither an {@link NonViralName#getAuthorshipCache() autorship}
392 * nor other name components. If this flag is set no other hybrid flags may
395 * @return the boolean value of the isHybridFormula flag
396 * @see #isMonomHybrid()
397 * @see #isBinomHybrid()
398 * @see #isTrinomHybrid()
400 public boolean isHybridFormula(){
401 return this.isHybridFormula
;
405 * @see #isHybridFormula()
407 public void setHybridFormula(boolean isHybridFormula
){
408 this.isHybridFormula
= isHybridFormula
;
412 * Returns the boolean value of the flag indicating whether this botanical
413 * taxon name is the name of an intergeneric hybrid (true) or not (false).
414 * In this case the multiplication sign is placed before the scientific
415 * name. If this flag is set no other hybrid flags may be set.
417 * @return the boolean value of the isMonomHybrid flag
418 * @see #isHybridFormula()
419 * @see #isBinomHybrid()
420 * @see #isTrinomHybrid()
422 public boolean isMonomHybrid(){
423 return this.isMonomHybrid
;
427 * @see #isMonomHybrid()
428 * @see #isBinomHybrid()
429 * @see #isTrinomHybrid()
431 public void setMonomHybrid(boolean isMonomHybrid
){
432 this.isMonomHybrid
= isMonomHybrid
;
436 * Returns the boolean value of the flag indicating whether this botanical
437 * taxon name is the name of an interspecific hybrid (true) or not (false).
438 * In this case the multiplication sign is placed before the species
439 * epithet. If this flag is set no other hybrid flags may be set.
441 * @return the boolean value of the isBinomHybrid flag
442 * @see #isHybridFormula()
443 * @see #isMonomHybrid()
444 * @see #isTrinomHybrid()
446 public boolean isBinomHybrid(){
447 return this.isBinomHybrid
;
451 * @see #isBinomHybrid()
452 * @see #isMonomHybrid()
453 * @see #isTrinomHybrid()
455 public void setBinomHybrid(boolean isBinomHybrid
){
456 this.isBinomHybrid
= isBinomHybrid
;
460 * Returns the boolean value of the flag indicating whether this botanical
461 * taxon name is the name of an infraspecific hybrid (true) or not (false).
462 * In this case the term "notho-" (optionally abbreviated "n-") is used as
463 * a prefix to the term denoting the infraspecific rank of this botanical
464 * taxon name. If this flag is set no other hybrid flags may be set.
466 * @return the boolean value of the isTrinomHybrid flag
467 * @see #isHybridFormula()
468 * @see #isMonomHybrid()
469 * @see #isBinomHybrid()
471 public boolean isTrinomHybrid(){
472 return this.isTrinomHybrid
;
476 * @see #isTrinomHybrid()
477 * @see #isBinomHybrid()
478 * @see #isMonomHybrid()
480 public void setTrinomHybrid(boolean isTrinomHybrid
){
481 this.isTrinomHybrid
= isTrinomHybrid
;
485 * Returns the boolean value of the flag indicating whether the specimen
486 * type of this botanical taxon name for a fungus is asexual (true) or not
487 * (false). This applies only in case of fungi. The Article 59 of the ICBN
488 * permits mycologists to give asexually reproducing fungi (anamorphs)
489 * separate names from their sexual states (teleomorphs).
491 * @return the boolean value of the isAnamorphic flag
493 public boolean isAnamorphic(){
494 return this.isAnamorphic
;
498 * @see #isAnamorphic()
500 public void setAnamorphic(boolean isAnamorphic
){
501 this.isAnamorphic
= isAnamorphic
;
506 * Returns the {@link NomenclaturalCode nomenclatural code} that governs
507 * the construction of this botanical taxon name, that is the
508 * International Code of Botanical Nomenclature. This method overrides
509 * the getNomeclaturalCode method from {@link TaxonNameBase#getNomeclaturalCode() TaxonNameBase}.
511 * @return the nomenclatural code for plants
512 * @see NonViralName#isCodeCompliant()
513 * @see TaxonNameBase#getHasProblem()
517 public NomenclaturalCode
getNomenclaturalCode(){
518 return NomenclaturalCode
.ICBN();