(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 }
115
116 @Transient
117 public abstract boolean isCodeCompliant();
118
119
120 @Transient
121 public Set<NameRelationship> getNameRelations() {
122 Set<NameRelationship> rels = new HashSet<NameRelationship>();
123 rels.addAll(getRelationsFromThisName());
124 rels.addAll(getRelationsToThisName());
125 return rels;
126 }
127 /**
128 * Add a name relationship to both names involved
129 * @param rel
130 */
131 public void addRelationshipToName(TaxonNameBase toName, NameRelationshipType type, String ruleConsidered){
132 NameRelationship rel = new NameRelationship(toName, this, type, ruleConsidered);
133 }
134 public void addRelationshipFromName(TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered){
135 NameRelationship rel = new NameRelationship(this, fromName, type, ruleConsidered);
136 }
137 protected void addNameRelationship(NameRelationship rel) {
138 if (rel!=null && rel.getToName().equals(this)){
139 this.relationsToThisName.add(rel);
140 }else if(rel!=null && rel.getFromName().equals(this)){
141 this.relationsFromThisName.add(rel);
142 }else{
143 //TODO: raise error???
144 }
145 }
146 public void removeNameRelationship(NameRelationship nameRelation) {
147 this.relationsToThisName.remove(nameRelation);
148 this.relationsFromThisName.remove(nameRelation);
149 }
150
151
152 @OneToMany(mappedBy="fromName")
153 @Cascade({CascadeType.SAVE_UPDATE})
154 public Set<NameRelationship> getRelationsFromThisName() {
155 return relationsFromThisName;
156 }
157 private void setRelationsFromThisName(Set<NameRelationship> relationsFromThisName) {
158 this.relationsFromThisName = relationsFromThisName;
159 }
160
161 @OneToMany(mappedBy="toName")
162 @Cascade({CascadeType.SAVE_UPDATE})
163 public Set<NameRelationship> getRelationsToThisName() {
164 return relationsToThisName;
165 }
166 private void setRelationsToThisName(Set<NameRelationship> relationsToThisName) {
167 this.relationsToThisName = relationsToThisName;
168 }
169
170
171
172 @OneToMany
173 @Cascade({CascadeType.SAVE_UPDATE})
174 public Set<NomenclaturalStatus> getStatus() {
175 return status;
176 }
177 protected void setStatus(Set<NomenclaturalStatus> status) {
178 this.status = status;
179 }
180 public void addStatus(NomenclaturalStatus status) {
181 this.status.add(status);
182 }
183 public void removeStatus(NomenclaturalStatus status) {
184 this.status.remove(status);
185 }
186
187
188 @Transient
189 public T getBasionym(){
190 //TODO: pick the right name relationships...
191 return null;
192 }
193 public void setBasionym(T basionym){
194 setBasionym(basionym, null);
195 }
196 public void setBasionym(T basionym, String ruleConsidered){
197 basionym.addRelationshipToName(this, NameRelationshipType.BASIONYM(), null);
198 }
199
200
201
202 //TODO for PROTOTYPE
203 @Transient
204 public INameCacheStrategy getCacheStrategy() {
205 return cacheStrategy;
206 }
207 public void setCacheStrategy(INameCacheStrategy cacheStrategy) {
208 this.cacheStrategy = cacheStrategy;
209 }
210
211 @ManyToOne
212 //@Cascade({CascadeType.SAVE_UPDATE})
213 public Rank getRank(){
214 return this.rank;
215 }
216 public void setRank(Rank rank){
217 this.rank = rank;
218 }
219
220 @ManyToOne
221 @Cascade({CascadeType.SAVE_UPDATE})
222 public ReferenceBase getNomenclaturalReference(){
223 return (ReferenceBase) this.nomenclaturalReference;
224 }
225 public void setNomenclaturalReference(INomenclaturalReference nomenclaturalReference){
226 this.nomenclaturalReference = nomenclaturalReference;
227 }
228
229
230 public String getAppendedPhrase(){
231 return this.appendedPhrase;
232 }
233 public void setAppendedPhrase(String appendedPhrase){
234 this.appendedPhrase = appendedPhrase;
235 }
236
237 public String getNomenclaturalMicroReference(){
238 return this.nomenclaturalMicroReference;
239 }
240 public void setNomenclaturalMicroReference(String nomenclaturalMicroReference){
241 this.nomenclaturalMicroReference = nomenclaturalMicroReference;
242 }
243
244 public boolean getHasProblem(){
245 return this.hasProblem;
246 }
247 public void setHasProblem(boolean hasProblem){
248 this.hasProblem = hasProblem;
249 }
250
251
252 @OneToMany
253 //TODO @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE_ORPHAN})
254 @Cascade(CascadeType.SAVE_UPDATE)
255 public Set<NameTypeDesignation> getNameTypeDesignations() {
256 return nameTypeDesignations;
257 }
258 protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
259 this.nameTypeDesignations = nameTypeDesignations;
260 }
261
262 public void addTypeDesignation(TaxonNameBase typeSpecies, ReferenceBase citation, String citationMicroReference, String originalNameString, boolean isRejectedType, boolean isConservedType) {
263 NameTypeDesignation td = new NameTypeDesignation(this, typeSpecies, citation, citationMicroReference, originalNameString, isRejectedType, isConservedType);
264 }
265 public void addTypeDesignation(Specimen typeSpecimen, TypeDesignationStatus status, ReferenceBase citation, String citationMicroReference, String originalNameString) {
266 this.homotypicalGroup.addTypeDesignation(typeSpecimen, status, citation, citationMicroReference, originalNameString);
267 }
268 public void removeTypeDesignation(NameTypeDesignation typeDesignation) {
269 this.nameTypeDesignations.remove(typeDesignation);
270 }
271 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
272 this.homotypicalGroup.removeTypeDesignation(typeDesignation);
273 }
274
275
276 @ManyToOne
277 @Cascade({CascadeType.SAVE_UPDATE})
278 public HomotypicalGroup getHomotypicalGroup() {
279 return homotypicalGroup;
280 }
281 public void setHomotypicalGroup(HomotypicalGroup newHomotypicalGroup) {
282 if(this.homotypicalGroup == newHomotypicalGroup) return;
283 if (homotypicalGroup != null) {
284 homotypicalGroup.typifiedNames.remove(this);
285 }
286 if (newHomotypicalGroup!= null) {
287 newHomotypicalGroup.typifiedNames.add(this);
288 }
289 this.homotypicalGroup = newHomotypicalGroup;
290 }
291
292 @Transient
293 public StrictReferenceBase getCitation(){
294 return null;
295 }
296
297 @Transient
298 public String getCitationString(){
299 return null;
300 }
301
302 @Transient
303 public String[] getProblems(){
304 return null;
305 }
306
307 /**
308 * returns year of according nomenclatural reference, null if nomenclatural
309 * reference does not exist
310 */
311 @Transient
312 public String getYear(){
313 return "";
314 }
315
316
317 /**
318 * Return a set of taxa that use this name
319 * @return
320 */
321 @Transient
322 public Set<Taxon> getTaxa(){
323 // TODO: implement this method via bidirectional TaxonBase-NameBase relation or use a DAO instead
324 return null;
325 }
326 /**
327 * Return a set of synonyms that use this name
328 * @return
329 */
330 @Transient
331 public Set<Synonym> getSynonyms(){
332 // TODO: implement this method via bidirectional TaxonBase-NameBase relation or use a DAO instead
333 return null;
334 }
335
336 @Transient
337 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
338 return this.getHomotypicalGroup().getTypeDesignations();
339 }
340
341 // Rank comparison shortcuts
342 @Transient
343 public boolean isSupraGeneric() {
344 return getRank().isSupraGeneric();
345 }
346 @Transient
347 public boolean isGenus() {
348 return getRank().isGenus();
349 }
350 @Transient
351 public boolean isInfraGeneric() {
352 return getRank().isInfraGeneric();
353 }
354 @Transient
355 public boolean isSpecies() {
356 return getRank().isSpecies();
357 }
358 @Transient
359 public boolean isInfraSpecific() {
360 return getRank().isInfraSpecific();
361 }
362 @Transient
363 public boolean isSupraGeneric(Rank rank) {
364 return getRank().isHigher(rank);
365 }
366 }