Changed locality from type String to type LanguageStringBase
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / TaxonNameBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.name;
11
12 import java.lang.reflect.Method;
13 import java.util.HashSet;
14 import java.util.Set;
15
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;
36
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;
43
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;
58
59 /**
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}.
66 * <P>
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
71 * </ul>
72 *
73 * @author m.doering
74 * @version 1.0
75 * @created 08-Nov-2007 13:06:57
76 */
77 @XmlAccessorType(XmlAccessType.FIELD)
78 @XmlType(name = "TaxonNameBase", propOrder = {
79 "appendedPhrase",
80 "nomenclaturalMicroReference",
81 "nomenclaturalReference",
82 "rank",
83 "fullTitleCache",
84 "protectedFullTitleCache",
85 "homotypicalGroup",
86 "typeDesignations",
87 "relationsFromThisName",
88 "relationsToThisName",
89 "status",
90 "descriptions"
91 // "taxonBases"
92 })
93 @XmlRootElement(name = "TaxonNameBase")
94 @Entity
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 {
98
99 static Logger logger = Logger.getLogger(TaxonNameBase.class);
100
101 private static Method methodDescriptionSetTaxonName;
102
103 @XmlElement(name = "FullTitleCache")
104 private String fullTitleCache;
105
106 //if true titleCache will not be automatically generated/updated
107 @XmlElement(name = "ProtectedFullTitleCache")
108 private boolean protectedFullTitleCache;
109
110 @XmlElementWrapper(name = "Descriptions")
111 @XmlElement(name = "Description")
112 private Set<TaxonNameDescription> descriptions = new HashSet<TaxonNameDescription>();
113
114 @XmlElement(name = "AppendedPhrase")
115 private String appendedPhrase;
116
117 @XmlElement(name = "NomenclaturalMicroReference")
118 private String nomenclaturalMicroReference;
119
120 @XmlAttribute
121 private boolean hasProblem = false;
122
123 @XmlElementWrapper(name = "TypeDesignations")
124 @XmlElement(name = "TypeDesignation")
125 @XmlIDREF
126 @XmlSchemaType(name = "IDREF")
127 private Set<TypeDesignationBase> typeDesignations = new HashSet<TypeDesignationBase>();
128
129 @XmlElement(name = "HomotypicalGroup")
130 @XmlIDREF
131 @XmlSchemaType(name = "IDREF")
132 private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
133
134 @XmlElementWrapper(name = "RelationsFromThisName")
135 @XmlElement(name = "RelationFromThisName")
136 @XmlIDREF
137 @XmlSchemaType(name = "IDREF")
138 private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
139
140 @XmlElementWrapper(name = "RelationsToThisName")
141 @XmlElement(name = "RelationToThisName")
142 @XmlIDREF
143 @XmlSchemaType(name = "IDREF")
144 private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
145
146 @XmlElementWrapper(name = "NomenclaturalStatus_")
147 @XmlElement(name = "NomenclaturalStatus")
148 @XmlIDREF
149 @XmlSchemaType(name = "IDREF")
150 private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
151
152 @XmlTransient
153 //@XmlElementWrapper(name = "TaxonBases")
154 //@XmlElement(name = "TaxonBase")
155 private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
156
157
158
159 @XmlElement(name = "Rank")
160 @XmlIDREF
161 @XmlSchemaType(name = "IDREF")
162 private Rank rank;
163
164 // FIXME: This must be an IDREF to the corresponding nomenclatural reference.
165 // @XmlTransient
166 // @XmlAnyElement
167 @XmlElement(name = "NomenclaturalReference", type = ReferenceBase.class)
168 @XmlIDREF
169 @XmlSchemaType(name = "IDREF")
170 private INomenclaturalReference nomenclaturalReference;
171
172 static Method methodTaxonBaseSetName;
173
174 // ************* CONSTRUCTORS *************/
175 /**
176 * Class constructor: creates a new empty taxon name.
177 *
178 * @see #TaxonNameBase(Rank)
179 * @see #TaxonNameBase(HomotypicalGroup)
180 * @see #TaxonNameBase(Rank, HomotypicalGroup)
181 */
182 public TaxonNameBase() {
183 this(null, null);
184 }
185 /**
186 * Class constructor: creates a new taxon name
187 * only containing its {@link Rank rank}.
188 *
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)
193 */
194 public TaxonNameBase(Rank rank) {
195 this(rank, null);
196 }
197 /**
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.
202 *
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)
207 */
208 public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
209 this(null, homotypicalGroup);
210 }
211 /**
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.
217 *
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)
223 */
224 public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
225 super();
226 this.setRank(rank);
227 if (homotypicalGroup == null){
228 homotypicalGroup = new HomotypicalGroup();
229 }
230 homotypicalGroup.addTypifiedName(this);
231 }
232
233 //********* METHODS **************************************/
234
235 //@Index(name="TaxonNameBaseTitleCacheIndex")
236 // public String getTitleCache(){
237 // return super.getTitleCache();
238 // }
239
240 /**
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.
248 *
249 * @return false
250 */
251 @Transient
252 public abstract boolean isCodeCompliant();
253
254 public abstract String generateFullTitle();
255
256 @Transient
257 public String getFullTitleCache(){
258 if (protectedFullTitleCache){
259 return this.fullTitleCache;
260 }
261 if (fullTitleCache == null){
262 this.setFullTitleCache(generateFullTitle(), protectedFullTitleCache);
263 }
264 return fullTitleCache;
265 }
266
267 public void setFullTitleCache(String fullTitleCache){
268 setFullTitleCache(fullTitleCache, PROTECTED);
269 }
270
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) + "...";
276 }
277 this.fullTitleCache = fullTitleCache;
278 this.setProtectedFullTitleCache(protectCache);
279 }
280
281 @Column(length=330)
282 @Deprecated //for hibernate use only
283 protected String getPersistentFullTitleCache(){
284 return getFullTitleCache();
285 }
286
287 @Deprecated //for hibernate use only
288 protected void setPersistentFullTitleCache(String fullTitleCache){
289 this.fullTitleCache = fullTitleCache;
290 }
291
292 public boolean isProtectedFullTitleCache() {
293 return protectedFullTitleCache;
294 }
295
296 public void setProtectedFullTitleCache(boolean protectedFullTitleCache) {
297 this.protectedFullTitleCache = protectedFullTitleCache;
298 }
299
300 /**
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.
304 *
305 * @see #getRelationsToThisName()
306 * @see #getRelationsFromThisName()
307 * @see #addNameRelationship(NameRelationship)
308 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
309 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
310 */
311 @Transient
312 public Set<NameRelationship> getNameRelations() {
313 Set<NameRelationship> rels = new HashSet<NameRelationship>();
314 rels.addAll(getRelationsFromThisName());
315 rels.addAll(getRelationsToThisName());
316 return rels;
317 }
318 /**
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}.
322 *
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)
330 */
331 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
332 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
333 }
334 /**
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}.
338 *
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)
346 */
347 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
348 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
349 }
350 /**
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.
356 *
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)
361 */
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);
367 }else{
368 //TODO: raise error???
369 }
370 }
371 /**
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.
377 *
378 * @param nameRelation the name relationship which should be deleted from one of both sets
379 * @see #getNameRelations()
380 */
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);
386 }
387
388
389 /**
390 * Does exactly the same as the addNameRelationship method provided that
391 * the given relationship is a name relationship.
392 *
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
398 */
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())
405 )){
406 TaxonNameBase fromName = ((NameRelationship)relation).getFromName();
407 TaxonNameBase toName = ((NameRelationship)relation).getToName();
408 fromName.getHomotypicalGroup().merge(toName.getHomotypicalGroup());
409 }
410 }else{
411 logger.warn("Relationship not of type NameRelationship!");
412 //TODO exception handling
413 }
414 }
415
416
417 /**
418 * Returns the set of all {@link NameRelationship name relationships}
419 * in which <i>this</i> taxon name is involved as a source.
420 *
421 * @see #getNameRelations()
422 * @see #getRelationsToThisName()
423 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
424 */
425 @OneToMany(mappedBy="relatedFrom", fetch= FetchType.LAZY)
426 @Cascade({CascadeType.SAVE_UPDATE})
427 public Set<NameRelationship> getRelationsFromThisName() {
428 return relationsFromThisName;
429 }
430 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
431 this.relationsFromThisName = relationsFromThisName;
432 }
433
434 /**
435 * Returns the set of all {@link NameRelationship name relationships}
436 * in which <i>this</i> taxon name is involved as a target.
437 *
438 * @see #getNameRelations()
439 * @see #getRelationsFromThisName()
440 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
441 */
442 @OneToMany(mappedBy="relatedTo", fetch= FetchType.LAZY)
443 @Cascade({CascadeType.SAVE_UPDATE})
444 public Set<NameRelationship> getRelationsToThisName() {
445 return relationsToThisName;
446 }
447 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
448 this.relationsToThisName = relationsToThisName;
449 }
450
451
452 /**
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.
457 *
458 * @see NomenclaturalStatus
459 * @see NomenclaturalStatusType
460 */
461 @OneToMany(fetch= FetchType.LAZY)
462 @Cascade({CascadeType.SAVE_UPDATE})
463 public Set<NomenclaturalStatus> getStatus() {
464 return status;
465 }
466 /**
467 * @see #getStatus()
468 */
469 protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
470 this.status = nomStatus;
471 }
472 /**
473 * Adds a new {@link NomenclaturalStatus nomenclatural status}
474 * to <i>this</i> taxon name's set of nomenclatural status.
475 *
476 * @param nomStatus the nomenclatural status to be added
477 * @see #getStatus()
478 */
479 public void addStatus(NomenclaturalStatus nomStatus) {
480 this.status.add(nomStatus);
481 }
482 /**
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
485 * will be nullified.
486 *
487 * @param nomStatus the nomenclatural status of <i>this</i> taxon name which should be deleted
488 * @see #getStatus()
489 */
490 public void removeStatus(NomenclaturalStatus nomStatus) {
491 //TODO to be implemented?
492 logger.warn("not yet fully implemented?");
493 this.status.remove(nomStatus);
494 }
495
496
497 /**
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).
504 */
505 @Transient
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())) {
511 return true;
512 }
513 }
514 return false;
515 }
516
517 /**
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.
523 */
524 @Transient
525 public T getBasionym(){
526 //TODO: pick the right name relationships...
527 logger.warn("get Basionym not yet implemented");
528 return null;
529 }
530 /**
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}.
536 *
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)
540 */
541 public void addBasionym(T basionym){
542 addBasionym(basionym, null);
543 }
544 /**
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}.
551 *
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)
556 */
557 public void addBasionym(T basionym, String ruleConsidered){
558 if (basionym != null){
559 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
560 }
561 }
562
563 /**
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.
568 *
569 * @see #getBasionym()
570 * @see #addBasionym(TaxonNameBase)
571 */
572 public void removeBasionym(){
573 //TODO implement
574 logger.warn("not yet implemented");
575 }
576
577
578
579 /**
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).
583 *
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
587 */
588 @Transient
589 public abstract S getCacheStrategy();
590 /**
591 * @see #getCacheStrategy()
592 */
593 public abstract void setCacheStrategy(S cacheStrategy);
594
595 /**
596 * Returns the taxonomic {@link Rank rank} of <i>this</i> taxon name.
597 *
598 * @see Rank
599 */
600 @ManyToOne
601 //@Cascade({CascadeType.SAVE_UPDATE})
602 public Rank getRank(){
603 return this.rank;
604 }
605 /**
606 * @see #getRank()
607 */
608 public void setRank(Rank rank){
609 this.rank = rank;
610 }
611
612 /**
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}.
617 *
618 * @see eu.etaxonomy.cdm.model.reference.INomenclaturalReference
619 * @see eu.etaxonomy.cdm.model.reference.ReferenceBase
620 */
621 @ManyToOne
622 @Cascade({CascadeType.SAVE_UPDATE})
623 @Target(ReferenceBase.class)
624 public INomenclaturalReference getNomenclaturalReference(){
625 return this.nomenclaturalReference;
626 }
627 /**
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.
631 *
632 * @see #getNomenclaturalReference()
633 */
634 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
635 this.nomenclaturalReference = nomenclaturalReference;
636 }
637
638 /**
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.
642 */
643 public String getAppendedPhrase(){
644 return this.appendedPhrase;
645 }
646 /**
647 * @see #getAppendedPhrase()
648 */
649 public void setAppendedPhrase(String appendedPhrase){
650 this.appendedPhrase = appendedPhrase;
651 }
652
653 /**
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.
660 */
661 //Details of the nomenclatural reference (protologue).
662 public String getNomenclaturalMicroReference(){
663 return this.nomenclaturalMicroReference;
664 }
665 /**
666 * @see #getNomenclaturalMicroReference()
667 */
668 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
669 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
670 }
671
672 /**
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.
677 *
678 * @return the boolean value of the hasProblem flag
679 */
680 public boolean getHasProblem(){
681 return this.hasProblem;
682 }
683 /**
684 * @see #getHasProblem()
685 */
686 public void setHasProblem(boolean hasProblem){
687 this.hasProblem = hasProblem;
688 }
689 /**
690 * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.
691 *
692 * @see #getHasProblem()
693 */
694 public boolean hasProblem(){
695 return getHasProblem();
696 }
697
698
699
700 //*********************** TYPE DESIGNATION *********************************************//
701
702
703
704 /**
705 * Returns the set of {@link TypeDesignationBase type designations} assigned
706 * to <i>this</i> taxon name.
707 * @see NameTypeDesignation
708 * @see SpecimenTypeDesignation
709 */
710 @ManyToMany
711 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
712 @Cascade(CascadeType.SAVE_UPDATE)
713 public Set<TypeDesignationBase> getTypeDesignations() {
714 return typeDesignations;
715 }
716
717 /**
718 * @see #getNameTypeDesignations()
719 */
720 private void setTypeDesignations(Set<TypeDesignationBase> typeDesignations) {
721 this.typeDesignations = typeDesignations;
722 }
723
724 /**
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.
727 *
728 * @param typeDesignation the type designation which should be deleted
729 */
730 public void removeTypeDesignation(TypeDesignationBase typeDesignation) {
731 logger.warn("not yet fully implemented: nullify the specimen type designation itself?");
732 this.typeDesignations.remove(typeDesignation);
733 }
734
735
736 /**
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.
744 *
745 * @see SpecimenTypeDesignation
746 * @see NameTypeDesignation
747 * @see HomotypicalGroup
748 */
749 @Transient
750 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignationsOfHomotypicalGroup() {
751 return this.getHomotypicalGroup().getSpecimenTypeDesignations();
752 }
753
754 //*********************** NAME TYPE DESIGNATION *********************************************//
755
756 /**
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.
762 *
763 * @see NameTypeDesignation
764 * @see SpecimenTypeDesignation
765 */
766 @Transient
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);
772 }
773 }
774 return result;
775 }
776
777 /**
778 * Creates and adds a new {@link NameTypeDesignation name type designation}
779 * to <i>this</i> taxon name's set of type designations.
780 *
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()
794 */
795 public void addNameTypeDesignation(TaxonNameBase typeSpecies,
796 ReferenceBase citation,
797 String citationMicroReference,
798 String originalNameString,
799 boolean isRejectedType,
800 boolean isConservedType,
801 boolean isLectoType,
802 boolean isNotDesignated,
803 boolean addToAllHomotypicNames) {
804 NameTypeDesignation nameTypeDesignation = new NameTypeDesignation(typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType, isNotDesignated);
805 addTypeDesignation(nameTypeDesignation, addToAllHomotypicNames);
806 }
807
808 //*********************** SPECIMEN TYPE DESIGNATION *********************************************//
809
810 /**
811 * Returns the set of {@link SpecimenTypeDesignation specimen type designations}
812 * that typify <i>this</i> taxon name.
813 */
814 @Transient
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);
820 }
821 }
822 return result;
823 }
824
825
826 /**
827 * Creates and adds a new {@link SpecimenTypeDesignation specimen type designation}
828 * to <i>this</i> taxon name's set of type designations.
829 *
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()
843 */
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);
853 }
854
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);
861
862 if (addToAllNames){
863 for (TaxonNameBase taxonName : this.getHomotypicalGroup().getTypifiedNames()){
864 if (taxonName != this){
865 taxonName.addTypeDesignation(typeDesignation, false);
866 }
867 }
868 }
869 }
870 return true;
871 }
872
873
874
875 //*********************** HOMOTYPICAL GROUP *********************************************//
876
877
878 /**
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.
882 *
883 * @see HomotypicalGroup
884 */
885 @ManyToOne
886 @Cascade({CascadeType.SAVE_UPDATE})
887 public HomotypicalGroup getHomotypicalGroup() {
888 return homotypicalGroup;
889 }
890 @Deprecated //only for bidirectional and persistence use
891 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
892 this.homotypicalGroup = newHomotypicalGroup;
893 }
894
895 // *************************************************************************//
896
897 /**
898 * @see #getNomenclaturalReference()
899 */
900 @Transient
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");
904 return null;
905 }
906
907 /**
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.
911 *
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()
916 */
917 @Transient
918 public String getCitationString(){
919 logger.warn("getCitationString not yet implemented");
920 return null;
921 }
922
923 /**
924 * Not yet implemented
925 */
926 @Transient
927 public String[] getProblems(){
928 logger.warn("getProblems not yet implemented");
929 return null;
930 }
931
932 /**
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.
936 *
937 * @return the string containing the publication date of <i>this</i> taxon name
938 * @see eu.etaxonomy.cdm.model.reference.INomenclaturalReference#getYear()
939 */
940 @Transient
941 public String getReferenceYear(){
942 if (this.getNomenclaturalReference() != null ){
943 return this.getNomenclaturalReference().getYear();
944 }else{
945 return null;
946 }
947 }
948
949 /**
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).
956 *
957 * @see #getTaxa()
958 * @see #getSynonyms()
959 */
960 @OneToMany(mappedBy="name", fetch= FetchType.LAZY)
961 public Set<TaxonBase> getTaxonBases() {
962 return this.taxonBases;
963 }
964 /**
965 * @see #getTaxonBases()
966 */
967 protected void setTaxonBases(Set<TaxonBase> taxonBases) {
968 if (taxonBases == null){
969 taxonBases = new HashSet<TaxonBase>();
970 }else{
971 this.taxonBases = taxonBases;
972 }
973 }
974 /**
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.
977 *
978 * @param taxonBase the taxon base to be added
979 * @see #getTaxonBases()
980 * @see #removeTaxonBase(TaxonBase)
981 */
982 //TODO protected
983 public void addTaxonBase(TaxonBase taxonBase){
984 taxonBases.add(taxonBase);
985 initMethods();
986 invokeSetMethod(methodTaxonBaseSetName, taxonBase);
987 }
988 /**
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.
990 *
991 * @param taxonBase the taxon base which should be removed from the corresponding set
992 * @see #getTaxonBases()
993 * @see #addTaxonBase(TaxonBase)
994 */
995 public void removeTaxonBase(TaxonBase taxonBase){
996 taxonBases.remove(taxonBase);
997 initMethods();
998 invokeSetMethodWithNull(methodTaxonBaseSetName, taxonBase);
999 }
1000
1001 private void initMethods(){
1002 if (methodTaxonBaseSetName == null){
1003 try {
1004 methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
1005 methodTaxonBaseSetName.setAccessible(true);
1006 } catch (Exception e) {
1007 e.printStackTrace();
1008 //TODO handle exception
1009 }
1010 }
1011 if (methodDescriptionSetTaxonName == null){
1012 try {
1013 methodDescriptionSetTaxonName = TaxonNameDescription.class.getDeclaredMethod("setTaxonName", TaxonNameBase.class);
1014 methodDescriptionSetTaxonName.setAccessible(true);
1015 } catch (Exception e) {
1016 e.printStackTrace();
1017 //TODO handle exception
1018 }
1019 }
1020 }
1021
1022
1023
1024 /**
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().
1028 *
1029 * @see eu.etaxonomy.cdm.model.taxon.Taxon
1030 * @see #getTaxonBases()
1031 * @see #getSynonyms()
1032 */
1033 @Transient
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);
1039 }
1040 }
1041 return result;
1042 }
1043
1044 /**
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().
1048 *
1049 * @see eu.etaxonomy.cdm.model.taxon.Synonym
1050 * @see #getTaxonBases()
1051 * @see #getTaxa()
1052 */
1053 @Transient
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);
1059 }
1060 }
1061 return result;
1062 }
1063
1064
1065 // *********** DESCRIPTIONS *************************************
1066
1067 /**
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.
1072 *
1073 * @see #addDescription(TaxonNameDescription)
1074 * @see #removeDescription(TaxonNameDescription)
1075 * @see eu.etaxonomy.cdm.model.description.TaxonNameDescription
1076 */
1077 @OneToMany(mappedBy="taxonName", fetch= FetchType.LAZY)
1078 @Cascade({CascadeType.SAVE_UPDATE})
1079 public Set<TaxonNameDescription> getDescriptions() {
1080 return descriptions;
1081 }
1082 /**
1083 * @see #getDescriptions()
1084 */
1085 protected void setDescriptions(Set<TaxonNameDescription> descriptions) {
1086 this.descriptions = descriptions;
1087 }
1088 /**
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.
1093 *
1094 * @param description the taxon name description to be added
1095 * @see #getDescriptions()
1096 * @see #removeDescription(TaxonNameDescription)
1097 */
1098 public void addDescription(TaxonNameDescription description) {
1099 initMethods();
1100 this.invokeSetMethod(methodDescriptionSetTaxonName, description);
1101 descriptions.add(description);
1102 }
1103 /**
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".
1107 *
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()
1112 */
1113 public void removeDescription(TaxonNameDescription description) {
1114 initMethods();
1115 this.invokeSetMethod(methodDescriptionSetTaxonName, null);
1116 descriptions.remove(description);
1117 }
1118
1119
1120
1121
1122
1123
1124 // ***********
1125 /**
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.
1130 *
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
1134 */
1135 public boolean isHomotypic(TaxonNameBase homoTypicName) {
1136 if (homoTypicName == null) {
1137 return false;
1138 }
1139 HomotypicalGroup homotypicGroup = homoTypicName.getHomotypicalGroup();
1140 if (homotypicGroup == null || this.getHomotypicalGroup() == null) {
1141 return false;
1142 }
1143 if (homotypicGroup.equals(this.getHomotypicalGroup())) {
1144 return true;
1145 }
1146 return false;
1147 }
1148
1149
1150
1151 //********* Rank comparison shortcuts ********************//
1152 /**
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.
1157 *
1158 * @see #isGenus()
1159 * @see #isInfraGeneric()
1160 * @see #isSpecies()
1161 * @see #isInfraSpecific()
1162 */
1163 @Transient
1164 public boolean isSupraGeneric() {
1165 if (rank == null){
1166 return false;
1167 }
1168 return getRank().isSupraGeneric();
1169 }
1170 /**
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.
1174 *
1175 * @see #isSupraGeneric()
1176 * @see #isInfraGeneric()
1177 * @see #isSpecies()
1178 * @see #isInfraSpecific()
1179 */
1180 @Transient
1181 public boolean isGenus() {
1182 if (rank == null){
1183 return false;
1184 }
1185 return getRank().isGenus();
1186 }
1187 /**
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.
1192 *
1193 * @see #isSupraGeneric()
1194 * @see #isGenus()
1195 * @see #isSpecies()
1196 * @see #isInfraSpecific()
1197 */
1198 @Transient
1199 public boolean isInfraGeneric() {
1200 if (rank == null){
1201 return false;
1202 }
1203 return getRank().isInfraGeneric();
1204 }
1205 /**
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.
1210 *
1211 * @see #isSupraGeneric()
1212 * @see #isGenus()
1213 * @see #isInfraGeneric()
1214 * @see #isInfraSpecific()
1215 */
1216 @Transient
1217 public boolean isSpecies() {
1218 if (rank == null){
1219 return false;
1220 }
1221 return getRank().isSpecies();
1222 }
1223 /**
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.
1228 *
1229 * @see #isSupraGeneric()
1230 * @see #isGenus()
1231 * @see #isInfraGeneric()
1232 * @see #isSpecies()
1233 */
1234 @Transient
1235 public boolean isInfraSpecific() {
1236 if (rank == null){
1237 return false;
1238 }
1239 return getRank().isInfraSpecific();
1240 }
1241
1242
1243 /**
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.
1251 *
1252 * @return null
1253 * @see #isCodeCompliant()
1254 * @see #getHasProblem()
1255 */
1256 @Transient
1257 abstract public NomenclaturalCode getNomenclaturalCode();
1258 /* (non-Javadoc)
1259 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
1260 */
1261 /**
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}.
1269 *
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()
1273 */
1274 @Override
1275 public String generateTitle() {
1276 // TODO Auto-generated method stub
1277 logger.warn("not yet implemented");
1278 return null;
1279 }
1280
1281 }