(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
13 import eu.etaxonomy.cdm.model.occurrence.Specimen;
14 import eu.etaxonomy.cdm.model.reference.INomenclaturalReference;
15 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
16 import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
17 import eu.etaxonomy.cdm.model.taxon.Synonym;
18 import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
19 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
20 import eu.etaxonomy.cdm.model.taxon.Taxon;
21 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
22 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
23 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
24 import eu.etaxonomy.cdm.model.common.IReferencedEntity;
25 import org.apache.log4j.Logger;
26 import org.hibernate.annotations.Cascade;
27 import org.hibernate.annotations.CascadeType;
28
29 import eu.etaxonomy.cdm.strategy.INameCacheStrategy;
30 import eu.etaxonomy.cdm.strategy.ITaxonNameParser;
31
32 import java.util.*;
33
34 import javax.persistence.*;
35
36 /**
37 * The upmost (abstract) class for scientific taxon names regardless of the any
38 * particular nomenclatural code. The scientific name including author strings and
39 * maybe year is stored in IdentifiableEntity.titleCache
40 *
41 * @author m.doering
42 * @version 1.0
43 * @created 08-Nov-2007 13:06:57
44 */
45 @Entity
46 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
47 public abstract class TaxonNameBase<T extends TaxonNameBase> extends IdentifiableEntity<TaxonNameBase> implements IReferencedEntity {
48 static Logger logger = Logger.getLogger(TaxonNameBase.class);
49 //The scientific name without author strings and year
50 private String nameCache;
51 //Non-atomised addition to a name not ruled by a nomenclatural code
52 private String appendedPhrase;
53 //Details of the nomenclatural reference (protologue). These are mostly (implicitly) pages but can also be figures or
54 //tables or any other element of a publication. {only if a nomenclatural reference exists}
55 private String nomenclaturalMicroReference;
56 //this flag will be set to true if the parseName method was unable to successfully parse the name
57 private boolean hasProblem = false;
58 protected Set<NameTypeDesignation> nameTypeDesignations = new HashSet();
59 private HomotypicalGroup homotypicalGroup = new HomotypicalGroup();
60 private Set<NameRelationship> relationsFromThisName = new HashSet();
61 private Set<NameRelationship> relationsToThisName = new HashSet();
62 private Set<NomenclaturalStatus> status = new HashSet();
63 private Rank rank;
64 //if set, the Reference.isNomenclaturallyRelevant flag should be set to true!
65 private INomenclaturalReference nomenclaturalReference;
66
67
68 //TODO
69 protected boolean protectedNameCache;
70
71 protected INameCacheStrategy cacheStrategy;
72
73 static protected ITaxonNameParser nameParser;
74
75 // /**
76 // * Returns a TaxonNameBase instance
77 // * @param fullName
78 // */
79 // abstract public static TaxonNameBase PARSED_NAME(String fullName);
80
81 // ************* CONSTRUCTORS *************/
82 public TaxonNameBase() {
83 super();
84 }
85 public TaxonNameBase(Rank rank) {
86 super();
87 this.setRank(rank);
88 }
89
90 //********* METHODS **************************************/
91
92 protected String generateNameCache(){
93 if (cacheStrategy == null){
94 logger.warn("No CacheStrategy defined for taxonName: " + this.toString());
95 return null;
96 }else{
97 return cacheStrategy.getNameCache(this);
98 }
99 }
100
101 public String getNameCache() {
102 if (protectedNameCache){
103 return this.nameCache;
104 }
105 // is title dirty, i.e. equal NULL?
106 if (nameCache == null){
107 this.nameCache = generateNameCache();
108 }
109 return nameCache;
110 }
111
112 public void setNameCache(String nameCache){
113 this.nameCache = nameCache;
114 // TODO this.setProtectedNameCache(true);
115 }
116 //TODO
117 // public void setTitleCache(String titleCache, boolean protectCache){
118 // this.titleCache = titleCache;
119 // this.setProtectedTitleCache(protectCache);
120 // }
121
122
123 @Transient
124 public abstract boolean isCodeCompliant();
125
126
127 @Transient
128 public Set<NameRelationship> getNameRelations() {
129 Set<NameRelationship> rels = new HashSet<NameRelationship>();
130 rels.addAll(getRelationsFromThisName());
131 rels.addAll(getRelationsToThisName());
132 return rels;
133 }
134 /**
135 * Add a name relationship to both names involved
136 * @param rel
137 */
138 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
139 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
140 }
141 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
142 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
143 }
144 protected void addNameRelationship(NameRelationship rel) {
145 if (rel!=null && rel.getToName().equals(this)){
146 this.relationsToThisName.add(rel);
147 }else if(rel!=null && rel.getFromName().equals(this)){
148 this.relationsFromThisName.add(rel);
149 }else{
150 //TODO: raise error???
151 }
152 }
153 public void removeNameRelationship(NameRelationship nameRelation) {
154 this.relationsToThisName.remove(nameRelation);
155 this.relationsFromThisName.remove(nameRelation);
156 }
157
158
159 @OneToMany(mappedBy="fromName")
160 @Cascade({CascadeType.SAVE_UPDATE})
161 public Set<NameRelationship> getRelationsFromThisName() {
162 return relationsFromThisName;
163 }
164 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
165 this.relationsFromThisName = relationsFromThisName;
166 }
167
168 @OneToMany(mappedBy="toName")
169 @Cascade({CascadeType.SAVE_UPDATE})
170 public Set<NameRelationship> getRelationsToThisName() {
171 return relationsToThisName;
172 }
173 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
174 this.relationsToThisName = relationsToThisName;
175 }
176
177
178
179 @OneToMany
180 @Cascade({CascadeType.SAVE_UPDATE})
181 public Set<NomenclaturalStatus> getStatus() {
182 return status;
183 }
184 protected void setStatus(Set<NomenclaturalStatus> status) {
185 this.status = status;
186 }
187 public void addStatus(NomenclaturalStatus status) {
188 this.status.add(status);
189 }
190 public void removeStatus(NomenclaturalStatus status) {
191 this.status.remove(status);
192 }
193
194
195 @Transient
196 public T getBasionym(){
197 //TODO: pick the right name relationships...
198 return null;
199 }
200 public void setBasionym(T basionym){
201 setBasionym(basionym, null);
202 }
203 public void setBasionym(T basionym, String ruleConsidered){
204 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), null);
205 }
206
207
208
209 //TODO for PROTOTYPE
210 @Transient
211 public INameCacheStrategy getCacheStrategy() {
212 return cacheStrategy;
213 }
214 public void setCacheStrategy(INameCacheStrategy cacheStrategy) {
215 this.cacheStrategy = cacheStrategy;
216 }
217
218 @ManyToOne
219 //@Cascade({CascadeType.SAVE_UPDATE})
220 public Rank getRank(){
221 return this.rank;
222 }
223 public void setRank(Rank rank){
224 this.rank = rank;
225 }
226
227 @ManyToOne
228 @Cascade({CascadeType.SAVE_UPDATE})
229 public ReferenceBase getNomenclaturalReference(){
230 return (ReferenceBase) this.nomenclaturalReference;
231 }
232 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
233 this.nomenclaturalReference = nomenclaturalReference;
234 }
235
236
237 public String getAppendedPhrase(){
238 return this.appendedPhrase;
239 }
240 public void setAppendedPhrase(String appendedPhrase){
241 this.appendedPhrase = appendedPhrase;
242 }
243
244 public String getNomenclaturalMicroReference(){
245 return this.nomenclaturalMicroReference;
246 }
247 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
248 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
249 }
250
251 public boolean getHasProblem(){
252 return this.hasProblem;
253 }
254 public void setHasProblem(boolean hasProblem){
255 this.hasProblem = hasProblem;
256 }
257
258
259 @OneToMany
260 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
261 @Cascade(CascadeType.SAVE_UPDATE)
262 public Set<NameTypeDesignation> getNameTypeDesignations() {
263 return nameTypeDesignations;
264 }
265 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
266 this.nameTypeDesignations = nameTypeDesignations;
267 }
268
269 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
270 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
271 }
272 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
273 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
274 }
275 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
276 this.nameTypeDesignations.remove(typeDesignation);
277 }
278 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
279 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
280 }
281
282
283 @ManyToOne
284 @Cascade({CascadeType.SAVE_UPDATE})
285 public HomotypicalGroup getHomotypicalGroup() {
286 return homotypicalGroup;
287 }
288 public void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
289 if(this.homotypicalGroup == newHomotypicalGroup) return;
290 if (homotypicalGroup != null) {
291 homotypicalGroup.typifiedNames.remove(this);
292 }
293 if (newHomotypicalGroup!= null) {
294 newHomotypicalGroup.typifiedNames.add(this);
295 }
296 this.homotypicalGroup = newHomotypicalGroup;
297 }
298
299 @Transient
300 public StrictReferenceBase getCitation(){
301 return null;
302 }
303
304 @Transient
305 public String getCitationString(){
306 return null;
307 }
308
309 @Transient
310 public String[] getProblems(){
311 return null;
312 }
313
314 /**
315 * returns year of according nomenclatural reference, null if nomenclatural
316 * reference does not exist
317 */
318 @Transient
319 public String getYear(){
320 return "";
321 }
322
323
324 /**
325 * Return a set of taxa that use this name
326 * @return
327 */
328 @Transient
329 public Set<Taxon> getTaxa(){
330 // TODO: implement this method via bidirectional TaxonBase-NameBase relation or use a DAO instead
331 return null;
332 }
333 /**
334 * Return a set of synonyms that use this name
335 * @return
336 */
337 @Transient
338 public Set<Synonym> getSynonyms(){
339 // TODO: implement this method via bidirectional TaxonBase-NameBase relation or use a DAO instead
340 return null;
341 }
342
343 @Transient
344 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
345 return this.getHomotypicalGroup().getTypeDesignations();
346 }
347
348 // Rank comparison shortcuts
349 @Transient
350 public boolean isSupraGeneric() {
351 return getRank().isSupraGeneric();
352 }
353 @Transient
354 public boolean isGenus() {
355 return getRank().isGenus();
356 }
357 @Transient
358 public boolean isInfraGeneric() {
359 return getRank().isInfraGeneric();
360 }
361 @Transient
362 public boolean isSpecies() {
363 return getRank().isSpecies();
364 }
365 @Transient
366 public boolean isInfraSpecific() {
367 return getRank().isInfraSpecific();
368 }
369 @Transient
370 public boolean isSupraGeneric(Rank rank) {
371 return getRank().isHigher(rank);
372 }
373 }