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 javax
.persistence
.Entity
;
13 import javax
.persistence
.FetchType
;
14 import javax
.persistence
.ManyToOne
;
15 import javax
.persistence
.Transient
;
16 import javax
.xml
.bind
.annotation
.XmlAccessType
;
17 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
18 import javax
.xml
.bind
.annotation
.XmlElement
;
19 import javax
.xml
.bind
.annotation
.XmlIDREF
;
20 import javax
.xml
.bind
.annotation
.XmlRootElement
;
21 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
22 import javax
.xml
.bind
.annotation
.XmlType
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.hibernate
.annotations
.Cascade
;
26 import org
.hibernate
.annotations
.CascadeType
;
27 import org
.hibernate
.envers
.Audited
;
28 import org
.hibernate
.search
.annotations
.ContainedIn
;
29 import org
.hibernate
.search
.annotations
.Indexed
;
30 import org
.springframework
.beans
.factory
.annotation
.Configurable
;
32 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
33 import eu
.etaxonomy
.cdm
.model
.name
.ITaxonNameBase
;
34 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
35 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
36 import eu
.etaxonomy
.cdm
.strategy
.cache
.taxon
.ITaxonCacheStrategy
;
37 import eu
.etaxonomy
.cdm
.strategy
.cache
.taxon
.TaxonBaseDefaultCacheStrategy
;
38 import eu
.etaxonomy
.cdm
.validation
.Level3
;
39 import eu
.etaxonomy
.cdm
.validation
.annotation
.HomotypicSynonymsShouldBelongToGroup
;
42 * The class for synonyms: these are {@link TaxonBase taxa} the {@link name.TaxonName taxon names}
43 * of which are not used by the {@link TaxonBase#getSec() reference} to designate a real
44 * taxon but are mentioned as taxon names that were oder are used by some other
45 * unspecified references to designate (at least to some extent) the same
46 * particular real taxon. Synonyms that are {@link #getAcceptedTaxon() attached} to an accepted {@link Taxon taxon}
47 * are actually meaningless.<BR>
48 * Splitting taxa in "accepted/valid" and "synonyms"
49 * makes it easier to handle particular relationships between
50 * ("accepted/valid") {@link Taxon taxa} on the one hand and ("synonym") taxa
54 * @created 08-Nov-2007 13:06:55
56 @XmlAccessorType(XmlAccessType
.FIELD
)
57 @XmlType(name
= "Synonym", propOrder
= {
63 @XmlRootElement(name
= "Synonym")
65 @Indexed(index
= "eu.etaxonomy.cdm.model.taxon.TaxonBase")
68 @HomotypicSynonymsShouldBelongToGroup(groups
= Level3
.class)
69 public class Synonym
extends TaxonBase
<ITaxonCacheStrategy
<Synonym
>> {
70 private static final long serialVersionUID
= 6977221584815363620L;
73 @SuppressWarnings("unused")
74 private static final Logger logger
= Logger
.getLogger(Synonym
.class);
77 @XmlElement(name
= "acceptedTaxon")
79 @XmlSchemaType(name
= "IDREF")
80 @ManyToOne(fetch
= FetchType
.LAZY
)
81 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
})
83 // @NotEmpty(groups = Level2.class,message="{eu.etaxonomy.cdm.model.taxon.Synonym.noOrphanedSynonyms.message}")
84 // @NotNull(groups = Level2.class)
85 private Taxon acceptedTaxon
;
88 @XmlElement(name
= "IsProParte")
89 private boolean proParte
= false;
91 @XmlElement(name
= "IsPartial")
92 private boolean partial
= false;
95 @XmlElement(name
= "Type")
97 @XmlSchemaType(name
= "IDREF")
98 @ManyToOne(fetch
=FetchType
.EAGER
)
99 private SynonymType type
;
101 //************************************* FACTORY ****************************/
103 * @see #NewInstance(TaxonName, Reference)
108 public static Synonym
NewInstance(ITaxonNameBase taxonName
, Reference sec
){
109 return NewInstance(TaxonName
.castAndDeproxy(taxonName
), sec
);
113 * Creates a new synonym instance with
114 * the {@link eu.etaxonomy.cdm.model.name.TaxonName taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
115 * using it as a synonym and not as an ("accepted/correct") {@link Taxon taxon}.
117 * @param TaxonName the taxon name used
118 * @param sec the reference using the taxon name
119 * @see #Synonym(TaxonName, Reference)
121 public static Synonym
NewInstance(TaxonName taxonName
, Reference sec
){
122 Synonym result
= new Synonym(taxonName
, sec
, null);
126 public static Synonym
NewInstance(TaxonName taxonName
, Reference sec
, String secDetail
){
127 Synonym result
= new Synonym(taxonName
, sec
, secDetail
);
131 // ************* CONSTRUCTORS *************/
133 * Class constructor: creates a new empty synonym instance.
135 * @see #Synonym(TaxonName, Reference)
137 //TODO should be private, but still produces Spring init errors
139 this.cacheStrategy
= new TaxonBaseDefaultCacheStrategy
<Synonym
>();
142 private Synonym(TaxonName taxonName
, Reference sec
, String secDetail
){
143 super(taxonName
, sec
, secDetail
);
144 this.cacheStrategy
= new TaxonBaseDefaultCacheStrategy
<Synonym
>();
147 //********************** GETTER/SETTER ******************************/
150 * Returns the "accepted/valid" {@link Taxon taxon}
153 public Taxon
getAcceptedTaxon() {
154 return this.acceptedTaxon
;
159 * @param acceptedTaxon the acceptedTaxon to set
161 protected void setAcceptedTaxon(Taxon acceptedTaxon
) {
162 if (acceptedTaxon
== null){
163 Taxon oldTaxon
= this.acceptedTaxon
;
164 this.acceptedTaxon
= null;
165 oldTaxon
.removeSynonym(this);
167 if (this.acceptedTaxon
!= null){
168 this.acceptedTaxon
.removeSynonym(this, false);
170 this.acceptedTaxon
= acceptedTaxon
;
171 this.acceptedTaxon
.addSynonym(this);
177 * Returns "true" if the proParte flag is set.
178 * This indicates that the {@link name.TaxonName taxon name} used as a
179 * {@link Synonym synonym} designated originally a real taxon which later has
180 * been split. In this case the synonym is therefore the synonym of at least
181 * two different ("accepted/valid") {@link Taxon taxa}.
183 public boolean isProParte() {
190 public void setProParte(boolean proParte
) {
191 this.proParte
= proParte
;
195 * Returns "true" if the <cod>partial</code> flag is set.
196 * This indicates that the {@link name.TaxonName taxon name} used as <code>this</code>
197 * {@link Synonym synonym} designated originally a real taxon which later has
198 * been lumped together with another one. In this case the
199 * ("accepted/valid") {@link Taxon taxon} has therefore at least
200 * two different synonyms (for the two lumped real taxa).
202 public boolean isPartial() {
209 public void setPartial(boolean partial
) {
210 this.partial
= partial
;
214 public SynonymType
getType() {
218 public void setType(SynonymType type
) {
224 //***************** METHODS **************************/
226 * Returns true if <i>this</i> is a synonym of the given taxon.
228 * @param taxon the taxon to check synonym for
229 * @return true if <i>this</i> is a synonm of the given taxon
231 * @see #getAcceptedTaxon()
234 public boolean isSynonymOf(Taxon taxon
){
235 return taxon
!= null && taxon
.equals(this.acceptedTaxon
);
240 public boolean isOrphaned() {
241 return this.acceptedTaxon
== null || this.acceptedTaxon
.isOrphaned();
245 * Checks if the synonym type is homotypic. If it is
246 * the name of <code>this</code> synonym is added to the {@link HomotypicalGroup
247 * homotypic group} of the {@link Taxon accepted taxon}.
249 private void checkHomotypic() {
250 if (type
!= null && type
.equals(SynonymType
.HOMOTYPIC_SYNONYM_OF())
251 && acceptedTaxon
!= null && acceptedTaxon
.getName() != null){
252 acceptedTaxon
.getName().getHomotypicalGroup().addTypifiedName(this.getName());
256 //*********************** CLONE ********************************************************/
259 public Object
clone() {
261 result
= (Synonym
)super.clone();
263 //no changes to accepted taxon, type, partial, proParte