Project

General

Profile

Download (13 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, String secDetail){
178
        super();
179
        if (taxonNameBase != null){
180
            this.invokeSetMethod(methodTaxonNameAddTaxonBase, taxonNameBase);
181
        }
182
        this.setSec(sec);
183
        this.setSecMicroReference(secDetail);
184
    }
185

    
186
//********* METHODS **************************************/
187

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

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

    
223

    
224

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

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

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

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

    
272

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

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

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

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

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

    
322

    
323

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

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

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

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

    
356
    /**
357
     * Returns <code>true</code> if <code>this</code>
358
     * taxon base is not part of any classification.
359
     * False otherwise
360
     * @return boolean
361
     */
362
    @Transient
363
    public abstract boolean isOrphaned();
364

    
365

    
366
    /**
367
     * @return
368
     */
369
    @Transient
370
    public Rank getNullSafeRank() {
371
        return name == null ? null : name.getRank();
372
    }
373

    
374
//*********************** CLONE ********************************************************/
375

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

    
390
            return result;
391
        } catch (CloneNotSupportedException e) {
392
            logger.warn("Object does not implement cloneable");
393
            e.printStackTrace();
394
            return null;
395
        }
396

    
397

    
398
    }
399

    
400

    
401
}
(10-10/20)