minor
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / taxon / TaxonBase.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.taxon;
11
12 import java.lang.reflect.Method;
13
14 import javax.persistence.Entity;
15 import javax.persistence.FetchType;
16 import javax.persistence.ManyToOne;
17 import javax.persistence.Transient;
18 import javax.validation.constraints.NotNull;
19 import javax.xml.bind.annotation.XmlAccessType;
20 import javax.xml.bind.annotation.XmlAccessorType;
21 import javax.xml.bind.annotation.XmlAttribute;
22 import javax.xml.bind.annotation.XmlElement;
23 import javax.xml.bind.annotation.XmlIDREF;
24 import javax.xml.bind.annotation.XmlSchemaType;
25 import javax.xml.bind.annotation.XmlType;
26
27 import org.apache.log4j.Logger;
28 import org.hibernate.annotations.Cascade;
29 import org.hibernate.annotations.CascadeType;
30 import org.hibernate.annotations.Index;
31 import org.hibernate.annotations.Table;
32 import org.hibernate.envers.Audited;
33 import org.hibernate.search.annotations.ClassBridge;
34 import org.hibernate.search.annotations.ClassBridges;
35 import org.hibernate.search.annotations.IndexedEmbedded;
36 import org.hibernate.search.annotations.Store;
37
38 import eu.etaxonomy.cdm.hibernate.search.AcceptedTaxonBridge;
39 import eu.etaxonomy.cdm.hibernate.search.ClassInfoBridge;
40 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
41 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
42 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
43 import eu.etaxonomy.cdm.model.reference.Reference;
44 import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
45 import eu.etaxonomy.cdm.validation.Level2;
46 import eu.etaxonomy.cdm.validation.Level3;
47 import eu.etaxonomy.cdm.validation.annotation.TaxonNameCannotBeAcceptedAndSynonym;
48
49 /**
50 * The upmost (abstract) class for the use of a {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} in a {@link eu.etaxonomy.cdm.model.reference.Reference reference}
51 * or within a taxonomic view/treatment either as a {@link Taxon taxon}
52 * ("accepted" respectively "correct" name) or as a (junior) {@link Synonym synonym}.
53 * Within a taxonomic view/treatment or a reference a taxon name can be used
54 * only in one of both described meanings. The reference using the taxon name
55 * is generally cited with "sec." (secundum, sensu). For instance:
56 * "<i>Juncus longirostris</i> Kuvaev sec. Kirschner, J. et al. 2002".
57 * <P>
58 * This class corresponds to: <ul>
59 * <li> TaxonConcept according to the TDWG ontology
60 * <li> TaxonConcept according to the TCS
61 * </ul>
62 *
63 * @author m.doering
64 * @created 08-Nov-2007 13:06:56
65 */
66 @XmlAccessorType(XmlAccessType.FIELD)
67 @XmlType(name = "TaxonBase", propOrder = {
68 "name",
69 "sec",
70 "doubtful",
71 "appendedPhrase",
72 "useNameCache"
73 })
74 @Entity
75 @Audited
76 //@PreFilter("hasPermission(filterObject, 'edit')")
77 @Table(appliesTo="TaxonBase", indexes = { @Index(name = "taxonBaseTitleCacheIndex", columnNames = { "titleCache" }) })
78 @TaxonNameCannotBeAcceptedAndSynonym(groups = Level3.class)
79 @ClassBridges({
80 @ClassBridge(name="classInfo",
81 index = org.hibernate.search.annotations.Index.YES,
82 store = Store.YES,
83 impl = ClassInfoBridge.class),
84 @ClassBridge(name="accTaxon", // TODO rename to acceptedTaxon, since we are usually not using abbreviations for field names
85 index = org.hibernate.search.annotations.Index.YES,
86 store = Store.YES,
87 impl = AcceptedTaxonBridge.class),
88 @ClassBridge(impl = eu.etaxonomy.cdm.hibernate.search.NomenclaturalSortOrderBrigde.class)
89 })
90 public abstract class TaxonBase<S extends IIdentifiableEntityCacheStrategy> extends IdentifiableEntity<S> implements Cloneable {
91 private static final long serialVersionUID = -3589185949928938529L;
92 private static final Logger logger = Logger.getLogger(TaxonBase.class);
93
94 private static Method methodTaxonNameAddTaxonBase;
95
96 static {
97 try {
98 methodTaxonNameAddTaxonBase = TaxonNameBase.class.getDeclaredMethod("addTaxonBase", TaxonBase.class);
99 methodTaxonNameAddTaxonBase.setAccessible(true);
100 } catch (Exception e) {
101 logger.error(e);
102 for(StackTraceElement ste : e.getStackTrace()) {
103 logger.error(ste);
104 }
105 }
106 }
107
108 //The assignment to the Taxon or to the Synonym class is not definitive
109 @XmlAttribute(name = "isDoubtful")
110 private boolean doubtful;
111
112
113 @XmlElement(name = "Name", required = true)
114 @XmlIDREF
115 @XmlSchemaType(name = "IDREF")
116 @ManyToOne(fetch = FetchType.LAZY)
117 @IndexedEmbedded
118 @Cascade(CascadeType.SAVE_UPDATE)
119 @NotNull(groups = Level2.class)
120 private TaxonNameBase<?,?> name;
121
122 // The concept reference
123 @XmlElement(name = "Sec")
124 @XmlIDREF
125 @XmlSchemaType(name = "IDREF")
126 @ManyToOne(fetch = FetchType.LAZY)
127 @Cascade(CascadeType.SAVE_UPDATE)
128 @NotNull(groups = Level2.class)
129 @IndexedEmbedded
130 private Reference<?> sec;
131
132
133 @XmlElement(name = "AppendedPhrase")
134 private String appendedPhrase;
135
136 @XmlAttribute(name= "UseNameCache")
137 private boolean useNameCache = false;
138
139
140 // ************* CONSTRUCTORS *************/
141 /**
142 * Class constructor: creates a new empty (abstract) taxon.
143 *
144 * @see #TaxonBase(TaxonNameBase, Reference)
145 */
146 protected TaxonBase(){
147 super();
148 }
149
150 /**
151 * Class constructor: creates a new (abstract) taxon with the
152 * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
153 * using it.
154 *
155 * @param taxonNameBase the taxon name used
156 * @param sec the reference using the taxon name
157 * @see #TaxonBase()
158 */
159 protected TaxonBase(TaxonNameBase taxonNameBase, Reference sec){
160 super();
161 if (taxonNameBase != null){
162 this.invokeSetMethod(methodTaxonNameAddTaxonBase, taxonNameBase);
163 }
164 this.setSec(sec);
165 }
166
167 //********* METHODS **************************************/
168
169 /**
170 * Generates and returns the string with the full scientific name (including
171 * authorship) of the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i>
172 * (abstract) taxon as well as the title of the {@link eu.etaxonomy.cdm.model.reference.Reference reference} using
173 * this taxon name. This string may be stored in the inherited
174 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
175 * This method overrides the generic and inherited generateTitle() method
176 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
177 *
178 * @return the string with the full scientific name of the taxon name
179 * and with the title of the reference involved in <i>this</i> (abstract) taxon
180 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
181 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
182 */
183 // @Override
184 // public String generateTitle() {
185 // String title;
186 // if (name != null && name.getTitleCache() != null){
187 // title = name.getTitleCache() + " sec. ";
188 // if (sec != null){
189 // title += sec.getTitleCache();
190 // }else{
191 // title += "???";
192 // }
193 // }else{
194 // title = this.toString();
195 // }
196 // return title;
197 // }
198
199 /**
200 * Returns the {@link TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
201 */
202 public TaxonNameBase getName(){
203 return this.name;
204 }
205
206 /*
207 * @see #getName
208 */
209 public void setName(TaxonNameBase name) {
210 if (this.name != null){
211 this.name.getTaxonBases().remove(this);
212 }
213 if(name != null) {
214 name.getTaxonBases().add(this);
215 }
216 this.name = name;
217 }
218
219 /**
220 * Returns the {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup homotypical group} of the
221 * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
222 */
223 @Transient
224 public HomotypicalGroup getHomotypicGroup(){
225 if (this.getName() == null){
226 return null;
227 }else{
228 return this.getName().getHomotypicalGroup();
229 }
230 }
231
232 /**
233 * Returns the boolean value indicating whether the assignment of <i>this</i>
234 * (abstract) taxon to the {@link Taxon Taxon} or to the {@link Synonym Synonym} class
235 * is definitive (false) or not (true). If this flag is set the use of <i>this</i> (abstract)
236 * taxon as an "accepted/correct" name or as a (junior) "synonym" might
237 * still change in the course of taxonomical working process.
238 */
239 public boolean isDoubtful(){
240 return this.doubtful;
241 }
242 /**
243 * @see #isDoubtful()
244 */
245 public void setDoubtful(boolean doubtful){
246 this.doubtful = doubtful;
247 }
248
249 /**
250 * Returns the {@link eu.etaxonomy.cdm.model.reference.Reference reference} of <i>this</i> (abstract) taxon.
251 * This is the reference or the treatment using the {@link TaxonNameBase taxon name}
252 * in <i>this</i> (abstract) taxon.
253 */
254 public Reference getSec() {
255 return sec;
256 }
257
258 /**
259 * @see #getSec()
260 */
261 public void setSec(Reference sec) {
262 this.sec = sec;
263 }
264
265
266
267 /**
268 * An appended phrase is a phrase that is added to the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name}
269 * 's title cache to be used just in this taxon. E.g. the phrase "sensu latu" may be added
270 * to the name to describe this taxon more precisely.
271 * If {@link #isUseNameCache()}
272 * @return the appendedPhrase
273 */
274 public String getAppendedPhrase() {
275 return appendedPhrase;
276 }
277
278 /**
279 * @param appendedPhrase the appendedPhrase to set
280 */
281 public void setAppendedPhrase(String appendedPhrase) {
282 this.appendedPhrase = appendedPhrase;
283 }
284
285 /**
286 * @return the useNameCache
287 */
288 public boolean isUseNameCache() {
289 return useNameCache;
290 }
291
292 /**
293 * @param useNameCache the useNameCache to set
294 */
295 public void setUseNameCache(boolean useNameCache) {
296 this.useNameCache = useNameCache;
297 }
298
299 @Transient
300 public abstract boolean isOrphaned();
301 //*********************** CLONE ********************************************************/
302
303 /**
304 * Clones <i>this</i> taxon. This is a shortcut that enables to create
305 * a new instance with empty taxon name and sec reference.
306 *
307 * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
308 * @see java.lang.Object#clone()
309 */
310 @Override
311 public Object clone() {
312 TaxonBase result;
313 try {
314 result = (TaxonBase)super.clone();
315 result.setSec(null);
316
317 return result;
318 } catch (CloneNotSupportedException e) {
319 logger.warn("Object does not implement cloneable");
320 e.printStackTrace();
321 return null;
322 }
323
324
325 }
326
327
328 }