2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.taxon
;
12 import java
.lang
.reflect
.Method
;
13 import java
.util
.List
;
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
;
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
;
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
;
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".
62 * This class corresponds to: <ul>
63 * <li> TaxonConcept according to the TDWG ontology
64 * <li> TaxonConcept according to the TCS
68 * @created 08-Nov-2007 13:06:56
70 @XmlAccessorType(XmlAccessType
.FIELD
)
71 @XmlType(name
= "TaxonBase", propOrder
= {
81 //@PreFilter("hasPermission(filterObject, 'edit')")
82 @Table(appliesTo
="TaxonBase", indexes
= { @Index(name
= "taxonBaseTitleCacheIndex", columnNames
= { "titleCache" }) })
83 @TaxonNameCannotBeAcceptedAndSynonym(groups
= Level3
.class)
85 @ClassBridge(name
="classInfo",
86 index
= org
.hibernate
.search
.annotations
.Index
.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
,
92 impl
= AcceptedTaxonBridge
.class),
93 @ClassBridge(impl
= eu
.etaxonomy
.cdm
.hibernate
.search
.NomenclaturalSortOrderBrigde
.class)
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);
99 private static Method methodTaxonNameAddTaxonBase
;
103 methodTaxonNameAddTaxonBase
= TaxonNameBase
.class.getDeclaredMethod("addTaxonBase", TaxonBase
.class);
104 methodTaxonNameAddTaxonBase
.setAccessible(true);
105 } catch (Exception e
) {
107 for(StackTraceElement ste
: e
.getStackTrace()) {
113 //The assignment to the Taxon or to the Synonym class is not definitive
114 @XmlAttribute(name
= "isDoubtful")
115 private boolean doubtful
;
118 @XmlElement(name
= "Name", required
= true)
120 @XmlSchemaType(name
= "IDREF")
121 @ManyToOne(fetch
= FetchType
.LAZY
)
122 @IndexedEmbedded(includeEmbeddedObjectId
=true)
123 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
124 @NotNull(groups
= Level2
.class)
125 private TaxonNameBase
<?
,?
> name
;
127 // The concept reference
128 @XmlElement(name
= "Sec")
130 @XmlSchemaType(name
= "IDREF")
131 @ManyToOne(fetch
= FetchType
.LAZY
)
132 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
133 @NotNull(groups
= Level2
.class)
135 private Reference
<?
> sec
;
138 @XmlElement(name
= "AppendedPhrase")
139 private String appendedPhrase
;
141 @XmlAttribute(name
= "UseNameCache")
142 private boolean useNameCache
= false;
144 @XmlAttribute(name
= "publish")
145 private boolean publish
= true;
148 // ************* CONSTRUCTORS *************/
150 * Class constructor: creates a new empty (abstract) taxon.
152 * @see #TaxonBase(TaxonNameBase, Reference)
154 protected TaxonBase(){
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}
163 * @param taxonNameBase the taxon name used
164 * @param sec the reference using the taxon name
167 protected TaxonBase(TaxonNameBase taxonNameBase
, Reference sec
){
169 if (taxonNameBase
!= null){
170 this.invokeSetMethod(methodTaxonNameAddTaxonBase
, taxonNameBase
);
175 //********* METHODS **************************************/
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}.
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()
192 // public String generateTitle() {
194 // if (name != null && name.getTitleCache() != null){
195 // title = name.getTitleCache() + " sec. ";
197 // title += sec.getTitleCache();
202 // title = this.toString();
208 public List
<TaggedText
> getTaggedTitle(){
209 return getCacheStrategy().getTaggedTitle(this);
215 * Returns the {@link TaxonNameBase taxon name} used in <i>this</i> (abstract) taxon.
217 public TaxonNameBase
getName(){
221 public void setName(TaxonNameBase name
) {
222 if (this.name
!= null){
223 this.name
.getTaxonBases().remove(this);
226 name
.getTaxonBases().add(this);
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.
236 public HomotypicalGroup
getHomotypicGroup(){
237 if (this.getName() == null){
240 return this.getName().getHomotypicalGroup();
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.
251 public boolean isDoubtful(){
252 return this.doubtful
;
257 public void setDoubtful(boolean doubtful
){
258 this.doubtful
= doubtful
;
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>.
270 public boolean isPublish() {
275 public void setPublish(boolean publish
) {
276 this.publish
= publish
;
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.
284 public Reference
getSec() {
291 public void setSec(Reference sec
) {
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
304 public String
getAppendedPhrase() {
305 return appendedPhrase
;
309 * @param appendedPhrase the appendedPhrase to set
311 public void setAppendedPhrase(String appendedPhrase
) {
312 this.appendedPhrase
= appendedPhrase
;
316 * @return the useNameCache
318 public boolean isUseNameCache() {
323 * @param useNameCache the useNameCache to set
325 public void setUseNameCache(boolean useNameCache
) {
326 this.useNameCache
= useNameCache
;
330 public abstract boolean isOrphaned();
337 public Rank
getNullSafeRank() {
338 return name
== null ?
null : name
.getRank();
341 //*********************** CLONE ********************************************************/
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.
347 * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
348 * @see java.lang.Object#clone()
351 public Object
clone() {
354 result
= (TaxonBase
)super.clone();
358 } catch (CloneNotSupportedException e
) {
359 logger
.warn("Object does not implement cloneable");