updated to trunk
[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 "publish",
72 "appendedPhrase",
73 "useNameCache"
74 })
75 @Entity
76 @Audited
77 //@PreFilter("hasPermission(filterObject, 'edit')")
78 @Table(appliesTo="TaxonBase", indexes = { @Index(name = "taxonBaseTitleCacheIndex", columnNames = { "titleCache" }) })
79 @TaxonNameCannotBeAcceptedAndSynonym(groups = Level3.class)
80 @ClassBridges({
81 @ClassBridge(name="classInfo",
82 index = org.hibernate.search.annotations.Index.YES,
83 store = Store.YES,
84 impl = ClassInfoBridge.class),
85 @ClassBridge(name="accTaxon", // TODO rename to acceptedTaxon, since we are usually not using abbreviations for field names
86 index = org.hibernate.search.annotations.Index.YES,
87 store = Store.YES,
88 impl = AcceptedTaxonBridge.class),
89 @ClassBridge(impl = eu.etaxonomy.cdm.hibernate.search.NomenclaturalSortOrderBrigde.class)
90 })
91 public abstract class TaxonBase<S extends IIdentifiableEntityCacheStrategy> extends IdentifiableEntity<S> implements Cloneable {
92 private static final long serialVersionUID = -3589185949928938529L;
93 private static final Logger logger = Logger.getLogger(TaxonBase.class);
94
95 private static Method methodTaxonNameAddTaxonBase;
96
97 static {
98 try {
99 methodTaxonNameAddTaxonBase = TaxonNameBase.class.getDeclaredMethod("addTaxonBase", TaxonBase.class);
100 methodTaxonNameAddTaxonBase.setAccessible(true);
101 } catch (Exception e) {
102 logger.error(e);
103 for(StackTraceElement ste : e.getStackTrace()) {
104 logger.error(ste);
105 }
106 }
107 }
108
109 //The assignment to the Taxon or to the Synonym class is not definitive
110 @XmlAttribute(name = "isDoubtful")
111 private boolean doubtful;
112
113 @XmlAttribute(name = "publish")
114 private boolean publish = true;
115
116 @XmlElement(name = "Name", required = true)
117 @XmlIDREF
118 @XmlSchemaType(name = "IDREF")
119 @ManyToOne(fetch = FetchType.LAZY)
120 @IndexedEmbedded
121 @Cascade(CascadeType.SAVE_UPDATE)
122 @NotNull(groups = Level2.class)
123 private TaxonNameBase<?,?> name;
124
125 // The concept reference
126 @XmlElement(name = "Sec")
127 @XmlIDREF
128 @XmlSchemaType(name = "IDREF")
129 @ManyToOne(fetch = FetchType.LAZY)
130 @Cascade(CascadeType.SAVE_UPDATE)
131 @NotNull(groups = Level2.class)
132 @IndexedEmbedded
133 private Reference<?> sec;
134
135
136 @XmlElement(name = "AppendedPhrase")
137 private String appendedPhrase;
138
139 @XmlAttribute(name= "UseNameCache")
140 private boolean useNameCache = false;
141
142
143 // ************* CONSTRUCTORS *************/
144 /**
145 * Class constructor: creates a new empty (abstract) taxon.
146 *
147 * @see #TaxonBase(TaxonNameBase, Reference)
148 */
149 protected TaxonBase(){
150 super();
151 }
152
153 /**
154 * Class constructor: creates a new (abstract) taxon with the
155 * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
156 * using it.
157 *
158 * @param taxonNameBase the taxon name used
159 * @param sec the reference using the taxon name
160 * @see #TaxonBase()
161 */
162 protected TaxonBase(TaxonNameBase taxonNameBase, Reference sec){
163 super();
164 if (taxonNameBase != null){
165 this.invokeSetMethod(methodTaxonNameAddTaxonBase, taxonNameBase);
166 }
167 this.setSec(sec);
168 }
169
170 //********* METHODS **************************************/
171
172 /**
173 * Generates and returns the string with the full scientific name (including
174 * authorship) of the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i>
175 * (abstract) taxon as well as the title of the {@link eu.etaxonomy.cdm.model.reference.Reference reference} using
176 * this taxon name. This string may be stored in the inherited
177 * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
178 * This method overrides the generic and inherited generateTitle() method
179 * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
180 *
181 * @return the string with the full scientific name of the taxon name
182 * and with the title of the reference involved in <i>this</i> (abstract) taxon
183 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
184 * @see eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
185 */
186 // @Override
187 // public String generateTitle() {
188 // String title;
189 // if (name != null && name.getTitleCache() != null){
190 // title = name.getTitleCache() + " sec. ";
191 // if (sec != null){
192 // title += sec.getTitleCache();
193 // }else{
194 // title += "???";
195 // }
196 // }else{
197 // title = this.toString();
198 // }
199 // return title;
200 // }
201
202 /**
203 * Returns the {@link TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
204 */
205 public TaxonNameBase getName(){
206 return this.name;
207 }
208
209 /*
210 * @see #getName
211 */
212 public void setName(TaxonNameBase name) {
213 if (this.name != null){
214 this.name.getTaxonBases().remove(this);
215 }
216 if(name != null) {
217 name.getTaxonBases().add(this);
218 }
219 this.name = name;
220 }
221
222 /**
223 * Returns the {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup homotypical group} of the
224 * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
225 */
226 @Transient
227 public HomotypicalGroup getHomotypicGroup(){
228 if (this.getName() == null){
229 return null;
230 }else{
231 return this.getName().getHomotypicalGroup();
232 }
233 }
234
235 /**
236 * Returns the boolean value indicating whether the assignment of <i>this</i>
237 * (abstract) taxon to the {@link Taxon Taxon} or to the {@link Synonym Synonym} class
238 * is definitive (false) or not (true). If this flag is set the use of <i>this</i> (abstract)
239 * taxon as an "accepted/correct" name or as a (junior) "synonym" might
240 * still change in the course of taxonomical working process.
241 */
242 public boolean isDoubtful(){
243 return this.doubtful;
244 }
245 /**
246 * @see #isDoubtful()
247 */
248 public void setDoubtful(boolean doubtful){
249 this.doubtful = doubtful;
250 }
251
252
253 /**
254 * Returns the boolean value indicating if this taxon should be withheld (<code>publish=false</code>) or not
255 * (<code>publish=true</code>) during any publication process to the general public.
256 * This publish flag implementation is preliminary and may be replaced by a more general
257 * implementation of READ rights in future.<BR>
258 * The default value is <code>true</code>.
259 */
260 public boolean isPublish() {
261 return publish;
262 }
263
264 public void setPublish(boolean publish) {
265 this.publish = publish;
266 }
267
268 /**
269 * Returns the {@link eu.etaxonomy.cdm.model.reference.Reference reference} of <i>this</i> (abstract) taxon.
270 * This is the reference or the treatment using the {@link TaxonNameBase taxon name}
271 * in <i>this</i> (abstract) taxon.
272 */
273 public Reference getSec() {
274 return sec;
275 }
276
277 /**
278 * @see #getSec()
279 */
280 public void setSec(Reference sec) {
281 this.sec = sec;
282 }
283
284
285
286 /**
287 * An appended phrase is a phrase that is added to the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name}
288 * 's title cache to be used just in this taxon. E.g. the phrase "sensu latu" may be added
289 * to the name to describe this taxon more precisely.
290 * If {@link #isUseNameCache()}
291 * @return the appendedPhrase
292 */
293 public String getAppendedPhrase() {
294 return appendedPhrase;
295 }
296
297 /**
298 * @param appendedPhrase the appendedPhrase to set
299 */
300 public void setAppendedPhrase(String appendedPhrase) {
301 this.appendedPhrase = appendedPhrase;
302 }
303
304 /**
305 * @return the useNameCache
306 */
307 public boolean isUseNameCache() {
308 return useNameCache;
309 }
310
311 /**
312 * @param useNameCache the useNameCache to set
313 */
314 public void setUseNameCache(boolean useNameCache) {
315 this.useNameCache = useNameCache;
316 }
317
318 @Transient
319 public abstract boolean isOrphaned();
320 //*********************** CLONE ********************************************************/
321
322 /**
323 * Clones <i>this</i> taxon. This is a shortcut that enables to create
324 * a new instance with empty taxon name and sec reference.
325 *
326 * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
327 * @see java.lang.Object#clone()
328 */
329 @Override
330 public Object clone() {
331 TaxonBase result;
332 try {
333 result = (TaxonBase)super.clone();
334 result.setSec(null);
335
336 return result;
337 } catch (CloneNotSupportedException e) {
338 logger.warn("Object does not implement cloneable");
339 e.printStackTrace();
340 return null;
341 }
342
343
344 }
345
346
347 }