Project

General

Profile

Download (12.8 KB) Statistics
| Branch: | Tag: | Revision:
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
import java.util.List;
14

    
15
import javax.persistence.Column;
16
import javax.persistence.Entity;
17
import javax.persistence.FetchType;
18
import javax.persistence.ManyToOne;
19
import javax.persistence.Transient;
20
import javax.validation.constraints.NotNull;
21
import javax.xml.bind.annotation.XmlAccessType;
22
import javax.xml.bind.annotation.XmlAccessorType;
23
import javax.xml.bind.annotation.XmlAttribute;
24
import javax.xml.bind.annotation.XmlElement;
25
import javax.xml.bind.annotation.XmlIDREF;
26
import javax.xml.bind.annotation.XmlSchemaType;
27
import javax.xml.bind.annotation.XmlType;
28

    
29
import org.apache.log4j.Logger;
30
import org.hibernate.annotations.Cascade;
31
import org.hibernate.annotations.CascadeType;
32
import org.hibernate.annotations.Index;
33
import org.hibernate.annotations.Table;
34
import org.hibernate.envers.Audited;
35
import org.hibernate.search.annotations.ClassBridge;
36
import org.hibernate.search.annotations.ClassBridges;
37
import org.hibernate.search.annotations.IndexedEmbedded;
38
import org.hibernate.search.annotations.Store;
39

    
40
import eu.etaxonomy.cdm.common.CdmUtils;
41
import eu.etaxonomy.cdm.hibernate.search.AcceptedTaxonBridge;
42
import eu.etaxonomy.cdm.hibernate.search.ClassInfoBridge;
43
import eu.etaxonomy.cdm.model.common.IPublishable;
44
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
45
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
46
import eu.etaxonomy.cdm.model.name.Rank;
47
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
48
import eu.etaxonomy.cdm.model.reference.Reference;
49
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
50
import eu.etaxonomy.cdm.strategy.cache.name.CacheUpdate;
51
import eu.etaxonomy.cdm.strategy.cache.taxon.ITaxonCacheStrategy;
52
import eu.etaxonomy.cdm.validation.Level2;
53
import eu.etaxonomy.cdm.validation.Level3;
54
import eu.etaxonomy.cdm.validation.annotation.NullOrNotEmpty;
55
import eu.etaxonomy.cdm.validation.annotation.TaxonNameCannotBeAcceptedAndSynonym;
56

    
57
/**
58
 * 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}
59
 * or within a taxonomic view/treatment either as a {@link Taxon taxon}
60
 * ("accepted" respectively "correct" name) or as a (junior) {@link Synonym synonym}.
61
 * Within a taxonomic view/treatment or a reference a taxon name can be used
62
 * only in one of both described meanings. The reference using the taxon name
63
 * is generally cited with "sec." (secundum, sensu). For instance:
64
 * "<i>Juncus longirostris</i> Kuvaev sec. Kirschner, J. et al. 2002".
65
 * <P>
66
 * This class corresponds to: <ul>
67
 * <li> TaxonConcept according to the TDWG ontology
68
 * <li> TaxonConcept according to the TCS
69
 * </ul>
70
 *
71
 * @author m.doering
72
 * @created 08-Nov-2007 13:06:56
73
 */
74
@XmlAccessorType(XmlAccessType.FIELD)
75
@XmlType(name = "TaxonBase", propOrder = {
76
    "name",
77
    "sec",
78
    "doubtful",
79
    "secMicroReference",
80
    "appendedPhrase",
81
    "useNameCache",
82
    "publish"
83
})
84
@Entity
85
@Audited
86
//@PreFilter("hasPermission(filterObject, 'edit')")
87
@Table(appliesTo="TaxonBase", indexes = { @Index(name = "taxonBaseTitleCacheIndex", columnNames = { "titleCache" }) })
88
@TaxonNameCannotBeAcceptedAndSynonym(groups = Level3.class)
89
@ClassBridges({
90
    @ClassBridge(name="classInfo",
91
            index = org.hibernate.search.annotations.Index.YES,
92
            store = Store.YES,
93
            impl = ClassInfoBridge.class),
94
    @ClassBridge(name="accTaxon", // TODO rename to acceptedTaxon, since we are usually not using abbreviations for field names
95
            index = org.hibernate.search.annotations.Index.YES,
96
            store = Store.YES,
97
            impl = AcceptedTaxonBridge.class),
98
    @ClassBridge(impl = eu.etaxonomy.cdm.hibernate.search.NomenclaturalSortOrderBrigde.class)
99
})
100
public abstract class TaxonBase<S extends ITaxonCacheStrategy> extends IdentifiableEntity<S> implements  IPublishable, Cloneable {
101
    private static final long serialVersionUID = -3589185949928938529L;
102
    private static final Logger logger = Logger.getLogger(TaxonBase.class);
103

    
104
    private static Method methodTaxonNameAddTaxonBase;
105

    
106
    static {
107
        try {
108
            methodTaxonNameAddTaxonBase = TaxonNameBase.class.getDeclaredMethod("addTaxonBase", TaxonBase.class);
109
            methodTaxonNameAddTaxonBase.setAccessible(true);
110
        } catch (Exception e) {
111
            logger.error(e);
112
            for(StackTraceElement ste : e.getStackTrace()) {
113
                logger.error(ste);
114
            }
115
        }
116
    }
117

    
118
    //The assignment to the Taxon or to the Synonym class is not definitive
119
    @XmlAttribute(name = "isDoubtful")
120
    private boolean doubtful;
121

    
122

    
123
    @XmlElement(name = "Name", required = true)
124
    @XmlIDREF
125
    @XmlSchemaType(name = "IDREF")
126
    @ManyToOne(fetch = FetchType.LAZY)
127
    @IndexedEmbedded(includeEmbeddedObjectId=true)
128
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
129
    @NotNull(groups = Level2.class)
130
    private TaxonNameBase<?,?> name;
131

    
132
    // The concept reference
133
    @XmlElement(name = "Sec")
134
    @XmlIDREF
135
    @XmlSchemaType(name = "IDREF")
136
    @ManyToOne(fetch = FetchType.LAZY)
137
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
138
    @NotNull(groups = Level2.class)
139
    @IndexedEmbedded
140
    private Reference sec;
141

    
142
    @XmlElement(name = "secMicroReference")
143
    @CacheUpdate(noUpdate ="titleCache")
144
    @NullOrNotEmpty
145
    @Column(length=255)
146
    private String secMicroReference;
147

    
148
    @XmlElement(name = "AppendedPhrase")
149
    private String appendedPhrase;
150

    
151
    @XmlAttribute(name= "UseNameCache")
152
    private boolean useNameCache = false;
153

    
154
    @XmlAttribute(name = "publish")
155
    private boolean publish = true;
156

    
157

    
158
// ************* CONSTRUCTORS *************/
159
    /**
160
     * Class constructor: creates a new empty (abstract) taxon.
161
     *
162
     * @see 	#TaxonBase(TaxonNameBase, Reference)
163
     */
164
    protected TaxonBase(){
165
        super();
166
    }
167

    
168
    /**
169
     * Class constructor: creates a new (abstract) taxon with the
170
     * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
171
     * using it.
172
     *
173
     * @param  taxonNameBase	the taxon name used
174
     * @param  sec				the reference using the taxon name
175
     * @see    #TaxonBase()
176
     */
177
    protected TaxonBase(TaxonNameBase taxonNameBase, Reference sec){
178
        super();
179
        if (taxonNameBase != null){
180
            this.invokeSetMethod(methodTaxonNameAddTaxonBase, taxonNameBase);
181
        }
182
        this.setSec(sec);
183
    }
184

    
185
//********* METHODS **************************************/
186

    
187
    /**
188
     * Generates and returns the string with the full scientific name (including
189
     * authorship) of the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i>
190
     * (abstract) taxon as well as the title of the {@link eu.etaxonomy.cdm.model.reference.Reference reference} using
191
     * this taxon name. This string may be stored in the inherited
192
     * {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache() titleCache} attribute.
193
     * This method overrides the generic and inherited generateTitle() method
194
     * from {@link eu.etaxonomy.cdm.model.common.IdentifiableEntity IdentifiableEntity}.
195
     *
196
     * @return  the string with the full scientific name of the taxon name
197
     *			and with the title of the reference involved in <i>this</i> (abstract) taxon
198
     * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#generateTitle()
199
     * @see  	eu.etaxonomy.cdm.model.common.IdentifiableEntity#getTitleCache()
200
     */
201
//	@Override
202
//	public String generateTitle() {
203
//		String title;
204
//		if (name != null && name.getTitleCache() != null){
205
//			title = name.getTitleCache() + " sec. ";
206
//			if (sec != null){
207
//				title += sec.getTitleCache();
208
//			}else{
209
//				title += "???";
210
//			}
211
//		}else{
212
//			title = this.toString();
213
//		}
214
//		return title;
215
//	}
216

    
217
    @Transient
218
    public List<TaggedText> getTaggedTitle(){
219
        return getCacheStrategy().getTaggedTitle(this);
220
    }
221

    
222

    
223

    
224
    /**
225
     * Returns the {@link TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
226
     */
227
    public TaxonNameBase getName(){
228
        return this.name;
229
    }
230

    
231
    public void setName(TaxonNameBase name) {
232
        if (this.name != null){
233
            this.name.getTaxonBases().remove(this);
234
        }
235
        if(name != null) {
236
            name.getTaxonBases().add(this);
237
        }
238
        this.name = name;
239
    }
240

    
241
    /**
242
     * Returns the {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup homotypical group} of the
243
     * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
244
     */
245
    @Transient
246
    public HomotypicalGroup getHomotypicGroup(){
247
        if (this.getName() == null){
248
            return null;
249
        }else{
250
            return this.getName().getHomotypicalGroup();
251
        }
252
    }
253

    
254
    /**
255
     * Returns the boolean value indicating whether the assignment of <i>this</i>
256
     * (abstract) taxon to the {@link Taxon Taxon} or to the {@link Synonym Synonym} class
257
     * is definitive (false) or not (true). If this flag is set the use of <i>this</i> (abstract)
258
     * taxon as an "accepted/correct" name or as a (junior) "synonym" might
259
     * still change in the course of taxonomical working process.
260
     */
261
    public boolean isDoubtful(){
262
        return this.doubtful;
263
    }
264
    /**
265
     * @see  #isDoubtful()
266
     */
267
    public void setDoubtful(boolean doubtful){
268
        this.doubtful = doubtful;
269
    }
270

    
271

    
272
    /**
273
     * Returns the boolean value indicating if this taxon should be withheld (<code>publish=false</code>) or not
274
     * (<code>publish=true</code>) during any publication process to the general public.
275
     * This publish flag implementation is preliminary and may be replaced by a more general
276
     * implementation of READ rights in future.<BR>
277
     * The default value is <code>true</code>.
278
     */
279
    @Override
280
    public boolean isPublish() {
281
        return publish;
282
    }
283

    
284
    @Override
285
    public void setPublish(boolean publish) {
286
        this.publish = publish;
287
    }
288

    
289
    /**
290
     * Returns the {@link eu.etaxonomy.cdm.model.reference.Reference reference} of <i>this</i> (abstract) taxon.
291
     * This is the reference or the treatment using the {@link TaxonNameBase taxon name}
292
     * in <i>this</i> (abstract) taxon.
293
     */
294
    public Reference getSec() {
295
        return sec;
296
    }
297
    /**
298
     * @see  #getSec()
299
     */
300
    public void setSec(Reference sec) {
301
        this.sec = sec;
302
    }
303

    
304
    /**
305
     * @return the micro reference (detail) for the sec(undum)
306
     * reference
307
     * @see #getSec()
308
     */
309
    public String getSecMicroReference() {
310
        return secMicroReference;
311
    }
312

    
313
    /**
314
     * @see #getSecMicroReference()
315
     * @see #getSec()
316
     */
317
    public void setSecMicroReference(String secMicroReference) {
318
        this.secMicroReference = CdmUtils.Nb(secMicroReference);
319
    }
320

    
321

    
322

    
323
    /**
324
     * An appended phrase is a phrase that is added to the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name}
325
     * 's title cache to be used just in this taxon. E.g. the phrase "sensu latu" may be added
326
     * to the name to describe this taxon more precisely.
327
     * If {@link #isUseNameCache()}
328
     * @return the appendedPhrase
329
     */
330
    public String getAppendedPhrase() {
331
        return appendedPhrase;
332
    }
333

    
334
    /**
335
     * @param appendedPhrase the appendedPhrase to set
336
     */
337
    public void setAppendedPhrase(String appendedPhrase) {
338
        this.appendedPhrase = appendedPhrase;
339
    }
340

    
341
    /**
342
     * @return the useNameCache
343
     */
344
    public boolean isUseNameCache() {
345
        return useNameCache;
346
    }
347

    
348
    /**
349
     * @param useNameCache the useNameCache to set
350
     */
351
    public void setUseNameCache(boolean useNameCache) {
352
        this.useNameCache = useNameCache;
353
    }
354

    
355
    @Transient
356
    public abstract boolean isOrphaned();
357

    
358

    
359
    /**
360
     * @return
361
     */
362
    @Transient
363
    public Rank getNullSafeRank() {
364
        return name == null ? null : name.getRank();
365
    }
366

    
367
//*********************** CLONE ********************************************************/
368

    
369
    /**
370
     * Clones <i>this</i> taxon. This is a shortcut that enables to create
371
     * a new instance with empty taxon name and sec reference.
372
     *
373
     * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
374
     * @see java.lang.Object#clone()
375
     */
376
    @Override
377
    public Object clone() {
378
        TaxonBase result;
379
        try {
380
            result = (TaxonBase)super.clone();
381
            result.setSec(null);
382

    
383
            return result;
384
        } catch (CloneNotSupportedException e) {
385
            logger.warn("Object does not implement cloneable");
386
            e.printStackTrace();
387
            return null;
388
        }
389

    
390

    
391
    }
392

    
393

    
394
}
(11-11/21)