(no commit message)
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / TaxonNameBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.model.name;
11
12 import eu.etaxonomy.cdm.model.occurrence.Specimen;
13 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
14 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
15 import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
16 import eu.etaxonomy.cdm.model.taxon.Synonym;
17 import eu.etaxonomy.cdm.model.taxon.Taxon;
18 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
19 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
20 import eu.etaxonomy.cdm.model.common.IParsable;
21 import eu.etaxonomy.cdm.model.common.IRelated;
22 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
23 import eu.etaxonomy.cdm.model.common.IReferencedEntity;
24 import eu.etaxonomy.cdm.model.common.RelationshipBase;
25
26
27 import org.apache.log4j.Logger;
28 import org.hibernate.annotations.Cascade;
29 import org.hibernate.annotations.CascadeType;
30 import org.hibernate.annotations.Target;
31
32 import eu.etaxonomy.cdm.strategy.cache.INameCacheStrategy;
33
34
35
36 import java.lang.reflect.Method;
37 import java.util.*;
38
39 import javax.persistence.*;
40
41 /**
42 * The upmost (abstract) class for scientific taxon names regardless of any
43 * particular nomenclatural code. The scientific name including author strings and
44 * maybe year can be stored as a string in the inherited {@link common.IdentifiableEntity#getTitleCache() titleCache} attribute.
45 * The scientific name string without author strings and year can be stored in the {@link #getNameCache() nameCache} attribute.
46 * The scientific taxon name does not depend on the use made of it
47 * in a publication or a treatment ({@link taxon.TaxonBase taxon concept respectively potential taxon})
48 * as an {@link taxon.Taxon "accepted" respectively "correct" (taxon) name}
49 * or as a {@link taxon.Synonym synonym}.
50 *
51 * @author m.doering
52 * @version 1.0
53 * @created 08-Nov-2007 13:06:57
54 */
55 @Entity
56 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
57 public abstract class TaxonNameBase<T extends TaxonNameBase, S extends INameCacheStrategy> extends IdentifiableEntity<TaxonNameBase> implements IReferencedEntity, IParsable, IRelated {
58 static Logger logger = Logger.getLogger(TaxonNameBase.class);
59 //Non-atomised addition to a name not ruled by a nomenclatural code
60 private String appendedPhrase;
61 private String nomenclaturalMicroReference;
62 private boolean hasProblem = false;
63 protected Set<NameTypeDesignation> nameTypeDesignations = new HashSet<NameTypeDesignation>();
64 private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
65 private Set<NameRelationship> relationsFromThisName = new HashSet<NameRelationship>();
66 private Set<NameRelationship> relationsToThisName = new HashSet<NameRelationship>();
67 private Set<NomenclaturalStatus> status = new HashSet<NomenclaturalStatus>();
68 private Set<TaxonBase> taxonBases = new HashSet<TaxonBase>();
69 private Rank rank;
70 private INomenclaturalReference nomenclaturalReference;
71
72 protected boolean protectedNameCache;
73
74 static Method methodTaxonBaseSetName;
75
76 // ************* CONSTRUCTORS *************/
77 /**
78 * Class constructor: creates a new empty taxon name instance.
79 *
80 * @see #TaxonNameBase(Rank)
81 * @see #TaxonNameBase(HomotypicalGroup)
82 * @see #TaxonNameBase(Rank, HomotypicalGroup)
83 */
84 public TaxonNameBase() {
85 this(null, null);
86 }
87 /**
88 * Class constructor: creates a new taxon name instance
89 * only containing its {@link common.Rank rank}.
90 *
91 * @param rank the rank to be assigned to this taxon name
92 * @see #TaxonNameBase()
93 * @see #TaxonNameBase(HomotypicalGroup)
94 * @see #TaxonNameBase(Rank, HomotypicalGroup)
95 */
96 public TaxonNameBase(Rank rank) {
97 this(rank, null);
98 }
99 /**
100 * Class constructor: creates a new taxon name instance
101 * only containing its {@link common.HomotypicalGroup homotypical group}.
102 * The new taxon name instance will be also added to the set of taxon names
103 * belonging to this homotypical group. If the homotypical group
104 * does not exist a new instance will be created for it.
105 *
106 * @param homotypicalGroup the homotypical group to which this taxon name belongs
107 * @see #TaxonNameBase()
108 * @see #TaxonNameBase(Rank)
109 * @see #TaxonNameBase(Rank, HomotypicalGroup)
110 */
111 public TaxonNameBase(HomotypicalGroup homotypicalGroup) {
112 this(null, homotypicalGroup);
113 }
114 /**
115 * Class constructor: creates a new instance of a taxon name
116 * only containing its {@link common.Rank rank} and
117 * its {@link common.HomotypicalGroup homotypical group}.
118 *
119 * @param rank the rank to be assigned to this taxon name
120 * @param homotypicalGroup the homotypical group to which this taxon name belongs
121 * @see #TaxonNameBase()
122 * @see #TaxonNameBase(Rank)
123 * @see #TaxonNameBase(HomotypicalGroup)
124 */
125 public TaxonNameBase(Rank rank, HomotypicalGroup homotypicalGroup) {
126 super();
127 this.setRank(rank);
128 if (homotypicalGroup == null){
129 homotypicalGroup = new HomotypicalGroup();
130 }
131 homotypicalGroup.addTypifiedName(this);
132 }
133
134 //********* METHODS **************************************/
135
136
137 /**
138 * Returns the boolean value "true" if the components of this taxon name
139 * follow the rules of the corresponding {@link NomenclaturalCode nomenclatural code},
140 * "false" otherwise. The nomenclatural code depends on
141 * the concrete name subclass ({@link BacterialName BacterialName},
142 * {@link BotanicalName BotanicalName}, {@link CultivarPlantName CultivarPlantName},
143 * {@link ZoologicalName ZoologicalName} or {@link ViralName ViralName})
144 * to which this taxon name belongs.
145 *
146 * @return the boolean value expressing the compliance of this taxon name to the nomenclatural code
147 */
148 @Transient
149 public abstract boolean isCodeCompliant();
150
151
152 /**
153 * Returns the set of all {@link NameRelationship name relationships}
154 * in which this taxon name is involved. A taxon name can be both source
155 * in some name relationships or target in some others.
156 *
157 * @see #getRelationsToThisName()
158 * @see #getRelationsFromThisName()
159 * @see #addNameRelationship(NameRelationship)
160 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
161 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
162 */
163 @Transient
164 public Set<NameRelationship> getNameRelations() {
165 Set<NameRelationship> rels = new HashSet<NameRelationship>();
166 rels.addAll(getRelationsFromThisName());
167 rels.addAll(getRelationsToThisName());
168 return rels;
169 }
170 /**
171 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from this taxon name to another taxon name
172 * and adds it both to the set of {@link #getRelationsFromThisName() relations from this taxon name} and
173 * to the set of {@link #getRelationsToThisName() relations to the other taxon name}.
174 *
175 * @param toName the taxon name of the target for this new name relationship
176 * @param type the type of this new name relationship
177 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
178 * @see #getRelationsToThisName()
179 * @see #getNameRelations()
180 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
181 * @see #addNameRelationship(NameRelationship)
182 */
183 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
184 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
185 }
186 /**
187 * Creates a new {@link NameRelationship#NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String) name relationship} from another taxon name to this taxon name
188 * and adds it both to the set of {@link #getRelationsToThisName() relations to this taxon name} and
189 * to the set of {@link #getRelationsFromThisName() relations from the other taxon name}.
190 *
191 * @param fromName the taxon name of the source for this new name relationship
192 * @param type the type of this new name relationship
193 * @param ruleConsidered the string which specifies the rule on which this name relationship is based
194 * @see #getRelationsFromThisName()
195 * @see #getNameRelations()
196 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
197 * @see #addNameRelationship(NameRelationship)
198 */
199 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
200 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
201 }
202 /**
203 * Adds an existing {@link NameRelationship name relationship} either to the set of
204 * {@link #getRelationsToThisName() relations to this taxon name} or to the set of
205 * {@link #getRelationsFromThisName() relations from this taxon name}. If neither the
206 * source nor the target of the name relationship match with this taxon
207 * no addition will be carried out.
208 *
209 * @param rel the name relationship to be added to one of this taxon name's name relationships sets
210 * @see #getNameRelations()
211 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
212 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
213 */
214 protected void addNameRelationship(NameRelationship rel) {
215 if (rel!=null && rel.getToName().equals(this)){
216 this.relationsToThisName.add(rel);
217 }else if(rel!=null && rel.getFromName().equals(this)){
218 this.relationsFromThisName.add(rel);
219 }else{
220 //TODO: raise error???
221 }
222 }
223 /**
224 * Removes one {@link NameRelationship name relationship} from one of both sets of
225 * {@link #getNameRelations() name relationships} in which this taxon name is involved.
226 * The name relationship will also be removed from one of both sets belonging
227 * to the second taxon name involved. Furthermore the fromName and toName
228 * attributes of the name relationship object will be nullified.
229 *
230 * @param nameRelation the name relationship which should be deleted from one of both sets
231 * @see #getNameRelations()
232 */
233 public void removeNameRelationship(NameRelationship nameRelation) {
234 //TODO to be implemented?
235 logger.warn("not yet fully implemented?");
236 this.relationsToThisName.remove(nameRelation);
237 this.relationsFromThisName.remove(nameRelation);
238 }
239
240
241 public void addRelationship(RelationshipBase relation) {
242 if (relation instanceof NameRelationship){
243 addNameRelationship((NameRelationship)relation);
244 }else{
245 //TODO exception handling
246 }
247 }
248
249
250 /**
251 * Returns the set of all {@link NameRelationship name relationships}
252 * in which this taxon name is involved as a source.
253 *
254 * @see #getNameRelations()
255 * @see #getRelationsToThisName()
256 * @see #addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
257 */
258 @OneToMany(mappedBy="relatedFrom", fetch= FetchType.EAGER)
259 @Cascade({CascadeType.SAVE_UPDATE})
260 public Set<NameRelationship> getRelationsFromThisName() {
261 return relationsFromThisName;
262 }
263 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
264 this.relationsFromThisName = relationsFromThisName;
265 }
266
267 /**
268 * Returns the set of all {@link NameRelationship name relationships}
269 * in which this taxon name is involved as a target.
270 *
271 * @see #getNameRelations()
272 * @see #getRelationsFromThisName()
273 * @see #addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
274 */
275 @OneToMany(mappedBy="relatedTo", fetch= FetchType.EAGER)
276 @Cascade({CascadeType.SAVE_UPDATE})
277 public Set<NameRelationship> getRelationsToThisName() {
278 return relationsToThisName;
279 }
280 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
281 this.relationsToThisName = relationsToThisName;
282 }
283
284
285 /**
286 * Returns the set of {@link NomenclaturalStatus nomenclatural status} assigned
287 * to this taxon name according to its corresponding nomenclature code.
288 * This includes the {@link NomenclaturalStatusType type} of the nomenclatural status
289 * and the nomenclatural code rule considered.
290 *
291 * @see NomenclaturalStatus
292 * @see NomenclaturalStatusType
293 */
294 @OneToMany(fetch= FetchType.EAGER)
295 @Cascade({CascadeType.SAVE_UPDATE})
296 public Set<NomenclaturalStatus> getStatus() {
297 return status;
298 }
299 /**
300 * @see #getStatus()
301 */
302 protected void setStatus(Set<NomenclaturalStatus> nomStatus) {
303 this.status = nomStatus;
304 }
305 /**
306 * Adds a new {@link NomenclaturalStatus nomenclatural status}
307 * to this taxon name's set of nomenclatural status.
308 *
309 * @param nomStatus the nomenclatural status to be added
310 * @see #getStatus()
311 */
312 public void addStatus(NomenclaturalStatus nomStatus) {
313 this.status.add(nomStatus);
314 }
315 /**
316 * Removes one element from the set of nomenclatural status of this taxon name.
317 * Type and ruleConsidered attributes of the nomenclatural status object
318 * will be nullified.
319 *
320 * @param nomStatus the nomenclatural status of this taxon name which should be deleted
321 * @see #getStatus()
322 */
323 public void removeStatus(NomenclaturalStatus nomStatus) {
324 //TODO to be implemented?
325 logger.warn("not yet fully implemented?");
326 this.status.remove(nomStatus);
327 }
328
329
330 /**
331 * Indicates if this taxon name is a {@link NameRelationshipType.BASIONYM() basionym}
332 * or a {@link NameRelationshipType.REPLACED_SYNONYM() replaced synonym}
333 * of any other taxon name. Returns true, if a basionym or a replaced synonym
334 * relationship from this taxon name to another taxon name exists,
335 * false otherwise (also in case this taxon name is the only one in the
336 * homotypical group).
337 */
338 @Transient
339 public boolean isOriginalCombination(){
340 Set<NameRelationship> relationsFromThisName = this.getRelationsFromThisName();
341 for (NameRelationship relation : relationsFromThisName) {
342 if (relation.getType().equals(NameRelationshipType.BASIONYM()) ||
343 relation.getType().equals(NameRelationshipType.REPLACED_SYNONYM())) {
344 return true;
345 }
346 }
347 return false;
348 }
349
350 /**
351 * Returns the taxon name which is the {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
352 * The basionym of a taxon name is its epithet-bringing synonym.
353 * For instance Pinus abies L. was published by Linnaeus and the botanist
354 * Karsten transferred later this taxon to the genus Picea. Therefore,
355 * Pinus abies L. is the basionym of the new combination Picea abies (L.) H. Karst.
356 */
357 @Transient
358 public T getBasionym(){
359 //TODO: pick the right name relationships...
360 return null;
361 }
362 /**
363 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name.
364 * The basionym relationship will be added to this taxon name
365 * and to the basionym. The basionym cannot have itself a basionym.
366 *
367 * @see #getBasionym()
368 * @see #setBasionym(TaxonNameBase, String)
369 */
370 public void setBasionym(T basionym){
371 setBasionym(basionym, null);
372 }
373 /**
374 * Assigns another taxon name as {@link NameRelationshipType.BASIONYM() basionym} of this taxon name
375 * and keeps the nomenclatural rule considered for it. The basionym
376 * relationship will be added to this taxon name and to the basionym.
377 * The basionym cannot have itself a basionym.
378 *
379 * @see #getBasionym()
380 * @see #setBasionym(TaxonNameBase)
381 */
382 public void setBasionym(T basionym, String ruleConsidered){
383 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), ruleConsidered);
384 }
385
386
387
388 @Transient
389 public abstract S getCacheStrategy();
390 public abstract void setCacheStrategy(S cacheStrategy);
391
392 /**
393 * Returns the taxonomic {@link Rank rank} of this taxon name.
394 *
395 * @see Rank
396 */
397 @ManyToOne
398 //@Cascade({CascadeType.SAVE_UPDATE})
399 public Rank getRank(){
400 return this.rank;
401 }
402 /**
403 * @see #getRank()
404 */
405 public void setRank(Rank rank){
406 this.rank = rank;
407 }
408
409 /**
410 * Returns the {@link reference.INomenclaturalReference nomenclatural reference} of this taxon name.
411 * The nomenclatural reference is here meant to be the one publication
412 * this taxon name was originally published in while fulfilling the formal
413 * requirements as specified by the corresponding nomenclatural code.
414 *
415 * @see reference.INomenclaturalReference
416 * @see reference.ReferenceBase
417 */
418 @ManyToOne
419 @Cascade({CascadeType.SAVE_UPDATE})
420 @Target(ReferenceBase.class)
421 public INomenclaturalReference getNomenclaturalReference(){
422 return (INomenclaturalReference) this.nomenclaturalReference;
423 }
424 /**
425 * Assigns a nomenclatural {@link reference.INomenclaturalReference nomenclatural reference} to this taxon name.
426 * The corresponding {@link reference.ReferenceBase.isNomenclaturallyRelevant nomenclaturally relevant flag} will be set to true
427 * as it is obviously used for nomenclatural purposes.
428 *
429 * @see #getNomenclaturalReference()
430 */
431 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
432 this.nomenclaturalReference = nomenclaturalReference;
433 }
434
435 /**
436 * Returns the appended phrase string assigned to this taxon name.
437 * The appended phrase is a non-atomised addition to a name. It is
438 * not ruled by a nomenclatural code.
439 */
440 public String getAppendedPhrase(){
441 return this.appendedPhrase;
442 }
443 /**
444 * @see #getAppendedPhrase()
445 */
446 public void setAppendedPhrase(String appendedPhrase){
447 this.appendedPhrase = appendedPhrase;
448 }
449
450 /**
451 * Returns the details string of the nomenclatural reference assigned
452 * to this taxon name. The details describe the exact localisation within
453 * the publication used as nomenclature reference. These are mostly
454 * (implicitly) pages but can also be figures or tables or any other
455 * element of a publication. A nomenclatural micro reference (details)
456 * requires the existence of a nomenclatural reference.
457 */
458 //Details of the nomenclatural reference (protologue).
459 public String getNomenclaturalMicroReference(){
460 return this.nomenclaturalMicroReference;
461 }
462 /**
463 * @see #getNomenclaturalMicroReference()
464 */
465 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
466 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
467 }
468
469 /**
470 * Returns the boolean value of the flag indicating whether the used {@link eu.etaxonomy.cdm.strategy.parser.INonViralNameParser parser}
471 * method was able to parse the taxon name string successfully (false)
472 * or not (true).
473 *
474 * @return the boolean value of the hasProblem flag
475 * @see #getNameCache()
476 */
477 public boolean getHasProblem(){
478 return this.hasProblem;
479 }
480 /**
481 * @see #getHasProblem()
482 */
483 public void setHasProblem(boolean hasProblem){
484 this.hasProblem = hasProblem;
485 }
486 /**
487 * Returns exactly the same boolean value as the {@link #getHasProblem() getHasProblem} method.
488 *
489 * @see #getHasProblem()
490 */
491 public boolean hasProblem(){
492 return getHasProblem();
493 }
494
495
496 /**
497 * Returns the set of {@link NameTypeDesignation name type designations} assigned
498 * to this taxon name the rank of which must be above "species".
499 * The name type designations include all the taxon names used to typify
500 * this name and eventually the rejected or conserved status
501 * of these designations.
502 *
503 * @see NameTypeDesignation
504 * @see SpecimenTypeDesignation
505 */
506 @OneToMany
507 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
508 @Cascade(CascadeType.SAVE_UPDATE)
509 public Set<NameTypeDesignation> getNameTypeDesignations() {
510 return nameTypeDesignations;
511 }
512 /**
513 * @see #getNameTypeDesignations()
514 */
515 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
516 this.nameTypeDesignations = nameTypeDesignations;
517 }
518
519 /**
520 * Creates and adds a new {@link NameTypeDesignation name type designation}
521 * to this taxon name's set of name type designations.
522 *
523 * @param typeSpecies the taxon name to be used as type of this taxon name
524 * @param citation the reference for this new designation
525 * @param citationMicroReference the string with the details (generally pages) within the reference
526 * @param originalNameString the taxon name used in the reference to assert this designation
527 * @param isRejectedType the boolean status for rejected
528 * @param isConservedType the boolean status for conserved
529 * @see #getNameTypeDesignations()
530 * @see #addTypeDesignation(Specimen, TypeDesignationStatus, ReferenceBase, String, String)
531 */
532 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
533 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
534 }
535 /**
536 * Adds a new {@link SpecimenTypeDesignation specimen type designation}
537 * to the set of specimen type designations assigned to the
538 * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
539 *
540 * @param typeSpecimen the specimen to be used as a type for this taxon name's homotypical group
541 * @param status the specimen type designation status
542 * @param citation the reference for this new specimen type designation
543 * @param citationMicroReference the string with the details (generally pages) within the reference
544 * @param originalNameString the taxon name used in the reference to assert this designation
545 * @see HomotypicalGroup#getTypeDesignations()
546 * @see #addTypeDesignation(TaxonNameBase, ReferenceBase, String, String, boolean, boolean)
547 * @see TypeDesignationStatus
548 */
549 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
550 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
551 }
552 /**
553 * Removes one element from the set of {@link NameTypeDesignation name type designations} of this taxon name.
554 * The name type designation itself will be nullified.
555 *
556 * @param typeDesignation the name type designation of this taxon name which should be deleted
557 * @see #getNameTypeDesignations()
558 * @see #removeTypeDesignation(SpecimenTypeDesignation)
559 */
560 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
561 this.nameTypeDesignations.remove(typeDesignation);
562 }
563 /**
564 * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
565 * {@link HomotypicalGroup homotypical group} to which this taxon name belongs.
566 * The specimen type designation itself will be nullified.
567 *
568 * @param typeDesignation the specimen type designation which should be deleted
569 * @see HomotypicalGroup#getTypeDesignations()
570 * @see #removeTypeDesignation(NameTypeDesignation)
571 */
572 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
573 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
574 }
575
576 /**
577 * Returns the {@link HomotypicalGroup homotypical group} to which
578 * this taxon name belongs. A homotypical group represents all names that
579 * share the same type specimens.
580 *
581 * @see HomotypicalGroup
582 */
583 @ManyToOne
584 @Cascade({CascadeType.SAVE_UPDATE})
585 public HomotypicalGroup getHomotypicalGroup() {
586 return homotypicalGroup;
587 }
588 @Deprecated //only for bidirectional and persistence use
589 protected void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
590 this.homotypicalGroup = newHomotypicalGroup;
591 }
592
593 @Transient
594 public StrictReferenceBase getCitation(){
595 logger.warn("getCitation not yet implemented");
596 return null;
597 }
598
599 @Transient
600 public String getCitationString(){
601 logger.warn("getCitationString not yet implemented");
602 return null;
603 }
604
605 @Transient
606 public String[] getProblems(){
607 logger.warn("getProblems not yet implemented");
608 return null;
609 }
610
611 /**
612 * returns year of according nomenclatural reference, null if nomenclatural
613 * reference does not exist
614 */
615 @Transient
616 public String getReferenceYear(){
617 if (this.getNomenclaturalReference() != null ){
618 return this.getNomenclaturalReference().getYear();
619 }else{
620 return null;
621 }
622 }
623
624 @OneToMany(mappedBy="name", fetch= FetchType.EAGER)
625 public Set<TaxonBase> getTaxonBases() {
626 return this.taxonBases;
627 }
628 protected void setTaxonBases(Set<TaxonBase> taxonBases) {
629 if (taxonBases == null){
630 taxonBases = new HashSet<TaxonBase>();
631 }else{
632 this.taxonBases = taxonBases;
633 }
634 }
635 //TODO protected
636 public void addTaxonBase(TaxonBase taxonBase){
637 taxonBases.add(taxonBase);
638 initMethods();
639 invokeSetMethod(methodTaxonBaseSetName, taxonBase);
640 }
641
642 private void initMethods(){
643 if (methodTaxonBaseSetName == null){
644 try {
645 methodTaxonBaseSetName = TaxonBase.class.getDeclaredMethod("setName", TaxonNameBase.class);
646 methodTaxonBaseSetName.setAccessible(true);
647 } catch (Exception e) {
648 e.printStackTrace();
649 //TODO handle exception
650 }
651 }
652 }
653
654
655 /**
656 * Return a set of taxa that use this name.
657 * @return Set<Taxon> The set of taxa this TaxonName belongs to
658 */
659 @Transient
660 public Set<Taxon> getTaxa(){
661 Set<Taxon> result = new HashSet<Taxon>();
662 for (TaxonBase taxonBase : this.taxonBases){
663 if (taxonBase instanceof Taxon){
664 result.add((Taxon)taxonBase);
665 }
666 }
667 return result;
668 }
669
670 /**
671 * Return a set of synonyms that use this name
672 * @return The set of synonyms this TaxonName belongs to
673 */
674 @Transient
675 public Set<Synonym> getSynonyms() {
676 Set<Synonym> result = new HashSet<Synonym>();
677 for (TaxonBase taxonBase : this.taxonBases){
678 if (taxonBase instanceof Synonym){
679 result.add((Synonym)taxonBase);
680 }
681 }
682 return result;
683 }
684
685 @Transient
686 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
687 return this.getHomotypicalGroup().getTypeDesignations();
688 }
689
690 // ***********
691 public boolean isHomotypic(TaxonNameBase homoTypicName) {
692 if (homoTypicName == null) {
693 return false;
694 }
695 HomotypicalGroup homotypicGroup = homoTypicName.getHomotypicalGroup();
696 if (homotypicGroup == null || this.getHomotypicalGroup() == null) {
697 return false;
698 }
699 if (homotypicGroup.equals(this.getHomotypicalGroup())) {
700 return true;
701 }
702 return false;
703 }
704
705
706
707 //********* Rank comparison shortcuts ********************//
708 @Transient
709 public boolean isSupraGeneric() {
710 return getRank().isSupraGeneric();
711 }
712 @Transient
713 public boolean isGenus() {
714 return getRank().isGenus();
715 }
716 @Transient
717 public boolean isInfraGeneric() {
718 return getRank().isInfraGeneric();
719 }
720 @Transient
721 public boolean isSpecies() {
722 return getRank().isSpecies();
723 }
724 @Transient
725 public boolean isInfraSpecific() {
726 return getRank().isInfraSpecific();
727 }
728
729
730 @Transient
731 abstract public NomenclaturalCode getNomeclaturalCode();
732
733 @Override
734 public String generateTitle() {
735 // TODO Auto-generated method stub
736 return null;
737 }
738
739
740 }