Project

General

Profile

Download (12 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.Entity;
16
import javax.persistence.FetchType;
17
import javax.persistence.ManyToOne;
18
import javax.persistence.Transient;
19
import javax.validation.constraints.NotNull;
20
import javax.xml.bind.annotation.XmlAccessType;
21
import javax.xml.bind.annotation.XmlAccessorType;
22
import javax.xml.bind.annotation.XmlAttribute;
23
import javax.xml.bind.annotation.XmlElement;
24
import javax.xml.bind.annotation.XmlIDREF;
25
import javax.xml.bind.annotation.XmlSchemaType;
26
import javax.xml.bind.annotation.XmlType;
27

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

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

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

    
99
    private static Method methodTaxonNameAddTaxonBase;
100

    
101
    static {
102
        try {
103
            methodTaxonNameAddTaxonBase = TaxonNameBase.class.getDeclaredMethod("addTaxonBase", TaxonBase.class);
104
            methodTaxonNameAddTaxonBase.setAccessible(true);
105
        } catch (Exception e) {
106
            logger.error(e);
107
            for(StackTraceElement ste : e.getStackTrace()) {
108
                logger.error(ste);
109
            }
110
        }
111
    }
112

    
113
    //The assignment to the Taxon or to the Synonym class is not definitive
114
    @XmlAttribute(name = "isDoubtful")
115
    private boolean doubtful;
116

    
117

    
118
    @XmlElement(name = "Name", required = true)
119
    @XmlIDREF
120
    @XmlSchemaType(name = "IDREF")
121
    @ManyToOne(fetch = FetchType.LAZY)
122
    @IndexedEmbedded
123
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
124
    @NotNull(groups = Level2.class)
125
    private TaxonNameBase<?,?> name;
126

    
127
    // The concept reference
128
    @XmlElement(name = "Sec")
129
    @XmlIDREF
130
    @XmlSchemaType(name = "IDREF")
131
    @ManyToOne(fetch = FetchType.LAZY)
132
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
133
    @NotNull(groups = Level2.class)
134
    @IndexedEmbedded
135
    private Reference<?> sec;
136

    
137

    
138
    @XmlElement(name = "AppendedPhrase")
139
    private String appendedPhrase;
140

    
141
    @XmlAttribute(name= "UseNameCache")
142
    private boolean useNameCache = false;
143

    
144
    @XmlAttribute(name = "publish")
145
    private boolean publish = true;
146

    
147

    
148
// ************* CONSTRUCTORS *************/
149
    /**
150
     * Class constructor: creates a new empty (abstract) taxon.
151
     *
152
     * @see 	#TaxonBase(TaxonNameBase, Reference)
153
     */
154
    protected TaxonBase(){
155
        super();
156
    }
157

    
158
    /**
159
     * Class constructor: creates a new (abstract) taxon with the
160
     * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
161
     * using it.
162
     *
163
     * @param  taxonNameBase	the taxon name used
164
     * @param  sec				the reference using the taxon name
165
     * @see    #TaxonBase()
166
     */
167
    protected TaxonBase(TaxonNameBase taxonNameBase, Reference sec){
168
        super();
169
        if (taxonNameBase != null){
170
            this.invokeSetMethod(methodTaxonNameAddTaxonBase, taxonNameBase);
171
        }
172
        this.setSec(sec);
173
    }
174

    
175
//********* METHODS **************************************/
176

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

    
207
    @Transient
208
    public List<TaggedText> getTaggedTitle(){
209
        return getCacheStrategy().getTaggedTitle(this);
210
    }
211

    
212

    
213

    
214
    /**
215
     * Returns the {@link TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
216
     */
217
    public TaxonNameBase getName(){
218
        return this.name;
219
    }
220

    
221
    public void setName(TaxonNameBase name) {
222
        if (this.name != null){
223
            this.name.getTaxonBases().remove(this);
224
        }
225
        if(name != null) {
226
            name.getTaxonBases().add(this);
227
        }
228
        this.name = name;
229
    }
230

    
231
    /**
232
     * Returns the {@link eu.etaxonomy.cdm.model.name.HomotypicalGroup homotypical group} of the
233
     * {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
234
     */
235
    @Transient
236
    public HomotypicalGroup getHomotypicGroup(){
237
        if (this.getName() == null){
238
            return null;
239
        }else{
240
            return this.getName().getHomotypicalGroup();
241
        }
242
    }
243

    
244
    /**
245
     * Returns the boolean value indicating whether the assignment of <i>this</i>
246
     * (abstract) taxon to the {@link Taxon Taxon} or to the {@link Synonym Synonym} class
247
     * is definitive (false) or not (true). If this flag is set the use of <i>this</i> (abstract)
248
     * taxon as an "accepted/correct" name or as a (junior) "synonym" might
249
     * still change in the course of taxonomical working process.
250
     */
251
    public boolean isDoubtful(){
252
        return this.doubtful;
253
    }
254
    /**
255
     * @see  #isDoubtful()
256
     */
257
    public void setDoubtful(boolean doubtful){
258
        this.doubtful = doubtful;
259
    }
260

    
261

    
262
    /**
263
     * Returns the boolean value indicating if this taxon should be withheld (<code>publish=false</code>) or not
264
     * (<code>publish=true</code>) during any publication process to the general public.
265
     * This publish flag implementation is preliminary and may be replaced by a more general
266
     * implementation of READ rights in future.<BR>
267
     * The default value is <code>true</code>.
268
     */
269
    @Override
270
    public boolean isPublish() {
271
        return publish;
272
    }
273

    
274
    @Override
275
    public void setPublish(boolean publish) {
276
        this.publish = publish;
277
    }
278

    
279
    /**
280
     * Returns the {@link eu.etaxonomy.cdm.model.reference.Reference reference} of <i>this</i> (abstract) taxon.
281
     * This is the reference or the treatment using the {@link TaxonNameBase taxon name}
282
     * in <i>this</i> (abstract) taxon.
283
     */
284
    public Reference getSec() {
285
        return sec;
286
    }
287

    
288
    /**
289
     * @see  #getSec()
290
     */
291
    public void setSec(Reference sec) {
292
        this.sec = sec;
293
    }
294

    
295

    
296

    
297
    /**
298
     * An appended phrase is a phrase that is added to the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name}
299
     * 's title cache to be used just in this taxon. E.g. the phrase "sensu latu" may be added
300
     * to the name to describe this taxon more precisely.
301
     * If {@link #isUseNameCache()}
302
     * @return the appendedPhrase
303
     */
304
    public String getAppendedPhrase() {
305
        return appendedPhrase;
306
    }
307

    
308
    /**
309
     * @param appendedPhrase the appendedPhrase to set
310
     */
311
    public void setAppendedPhrase(String appendedPhrase) {
312
        this.appendedPhrase = appendedPhrase;
313
    }
314

    
315
    /**
316
     * @return the useNameCache
317
     */
318
    public boolean isUseNameCache() {
319
        return useNameCache;
320
    }
321

    
322
    /**
323
     * @param useNameCache the useNameCache to set
324
     */
325
    public void setUseNameCache(boolean useNameCache) {
326
        this.useNameCache = useNameCache;
327
    }
328

    
329
    @Transient
330
    public abstract boolean isOrphaned();
331

    
332

    
333
    /**
334
     * @return
335
     */
336
    @Transient
337
    public Rank getNullSafeRank() {
338
        return name == null ? null : name.getRank();
339
    }
340

    
341
//*********************** CLONE ********************************************************/
342

    
343
    /**
344
     * Clones <i>this</i> taxon. This is a shortcut that enables to create
345
     * a new instance with empty taxon name and sec reference.
346
     *
347
     * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
348
     * @see java.lang.Object#clone()
349
     */
350
    @Override
351
    public Object clone() {
352
        TaxonBase result;
353
        try {
354
            result = (TaxonBase)super.clone();
355
            result.setSec(null);
356

    
357
            return result;
358
        } catch (CloneNotSupportedException e) {
359
            logger.warn("Object does not implement cloneable");
360
            e.printStackTrace();
361
            return null;
362
        }
363

    
364

    
365
    }
366

    
367

    
368
}
(10-10/20)