Project

General

Profile

Download (8.26 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 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;
23

    
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;
31

    
32
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
33
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
34
import eu.etaxonomy.cdm.model.reference.Reference;
35
import eu.etaxonomy.cdm.strategy.cache.taxon.ITaxonCacheStrategy;
36
import eu.etaxonomy.cdm.strategy.cache.taxon.TaxonBaseDefaultCacheStrategy;
37
import eu.etaxonomy.cdm.validation.Level3;
38
import eu.etaxonomy.cdm.validation.annotation.HomotypicSynonymsShouldBelongToGroup;
39

    
40
/**
41
 * The class for synonyms: these are {@link TaxonBase taxa} the {@link name.TaxonNameBase taxon names}
42
 * of which are not used by the {@link TaxonBase#getSec() reference} to designate a real
43
 * taxon but are mentioned as taxon names that were oder are used by some other
44
 * unspecified references to designate (at least to some extent) the same
45
 * particular real taxon. Synonyms that are {@link #getAcceptedTaxon() attached} to an accepted {@link Taxon taxon}
46
 * are actually meaningless.<BR>
47
 * Splitting taxa in "accepted/valid" and "synonyms"
48
 * makes it easier to handle particular relationships between
49
 * ("accepted/valid") {@link Taxon taxa} on the one hand and ("synonym") taxa
50
 *  on the other.
51
 *
52
 * @author m.doering
53
 * @created 08-Nov-2007 13:06:55
54
 */
55
@XmlAccessorType(XmlAccessType.FIELD)
56
@XmlType(name = "Synonym", propOrder = {
57
    "acceptedTaxon",
58
    "type",
59
    "proParte",
60
    "partial"
61
})
62
@XmlRootElement(name = "Synonym")
63
@Entity
64
@Indexed(index = "eu.etaxonomy.cdm.model.taxon.TaxonBase")
65
@Audited
66
@Configurable
67
@HomotypicSynonymsShouldBelongToGroup(groups = Level3.class)
68
public class Synonym extends TaxonBase<ITaxonCacheStrategy<Synonym>> {
69
    private static final long serialVersionUID = 6977221584815363620L;
70

    
71

    
72
    @SuppressWarnings("unused")
73
	private static final Logger logger = Logger.getLogger(Synonym.class);
74

    
75

    
76
    @XmlElement(name = "acceptedTaxon")
77
    @XmlIDREF
78
    @XmlSchemaType(name = "IDREF")
79
    @ManyToOne(fetch = FetchType.LAZY)
80
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
81
    @ContainedIn
82
//  @NotEmpty(groups = Level2.class,message="{eu.etaxonomy.cdm.model.taxon.Synonym.noOrphanedSynonyms.message}")
83
//    @NotNull(groups = Level2.class)
84
    private Taxon acceptedTaxon;
85

    
86

    
87
    @XmlElement(name = "IsProParte")
88
    private boolean proParte = false;
89

    
90
    @XmlElement(name = "IsPartial")
91
    private boolean partial = false;
92

    
93

    
94
    @XmlElement(name = "Type")
95
    @XmlIDREF
96
    @XmlSchemaType(name = "IDREF")
97
    @ManyToOne(fetch=FetchType.EAGER)
98
    private SynonymType type;
99

    
100
//************************************* FACTORY ****************************/
101

    
102
    /**
103
     * Creates a new synonym instance with
104
     * the {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon name} used and the {@link eu.etaxonomy.cdm.model.reference.Reference reference}
105
     * using it as a synonym and not as an ("accepted/correct") {@link Taxon taxon}.
106
     *
107
     * @param  taxonNameBase    the taxon name used
108
     * @param  sec              the reference using the taxon name
109
     * @see                     #Synonym(TaxonNameBase, Reference)
110
     */
111
    public static Synonym NewInstance(TaxonNameBase taxonName, Reference sec){
112
        Synonym result = new Synonym(taxonName, sec, null);
113
        return result;
114
    }
115

    
116
    public static Synonym NewInstance(TaxonNameBase taxonName, Reference sec, String secDetail){
117
        Synonym result = new Synonym(taxonName, sec, secDetail);
118
        return result;
119
    }
120

    
121
// ************* CONSTRUCTORS *************/
122
	/**
123
	 * Class constructor: creates a new empty synonym instance.
124
	 *
125
	 * @see 	#Synonym(TaxonNameBase, Reference)
126
	 */
127
	//TODO should be private, but still produces Spring init errors
128
	public Synonym(){
129
		this.cacheStrategy = new TaxonBaseDefaultCacheStrategy<Synonym>();
130
	}
131

    
132
	private Synonym(TaxonNameBase taxonNameBase, Reference sec, String secDetail){
133
		super(taxonNameBase, sec, secDetail);
134
		this.cacheStrategy = new TaxonBaseDefaultCacheStrategy<Synonym>();
135
	}
136

    
137
//********************** GETTER/SETTER ******************************/
138

    
139
	/**
140
	 * Returns the "accepted/valid" {@link Taxon taxon}
141
	 *
142
	 */
143
	public Taxon getAcceptedTaxon() {
144
		return this.acceptedTaxon;
145
	}
146

    
147

    
148
    /**
149
     * @param acceptedTaxon the acceptedTaxon to set
150
     */
151
    protected void setAcceptedTaxon(Taxon acceptedTaxon) {
152
        if (acceptedTaxon == null){
153
            Taxon oldTaxon = this.acceptedTaxon;
154
            this.acceptedTaxon = null;
155
            oldTaxon.removeSynonym(this);
156
        }else{
157
            if (this.acceptedTaxon != null){
158
                this.acceptedTaxon.removeSynonym(this, false);
159
            }
160
            this.acceptedTaxon = acceptedTaxon;
161
            this.acceptedTaxon.addSynonym(this);
162
            checkHomotypic();
163
        }
164
    }
165

    
166
    /**
167
     * Returns "true" if the proParte flag is set.
168
     * This indicates that the {@link name.TaxonNameBase taxon name} used as a
169
     * {@link Synonym synonym} designated originally a real taxon which later has
170
     * been split. In this case the synonym is therefore the synonym of at least
171
     * two different ("accepted/valid") {@link Taxon taxa}.
172
     */
173
    public boolean isProParte() {
174
        return proParte;
175
    }
176

    
177
    /**
178
     * @see #isProParte()
179
     */
180
    public void setProParte(boolean proParte) {
181
        this.proParte = proParte;
182
    }
183

    
184
    /**
185
     * Returns "true" if the ProParte flag is set.
186
     * This indicates that the {@link name.TaxonNameBase taxon name} used as <code>this</code>
187
     * {@link Synonym synonym} designated originally a real taxon which later has
188
     * been lumped together with another one. In this case the
189
     * ("accepted/valid") {@link Taxon taxon} has therefore at least
190
     * two different synonyms (for the two lumped real taxa).
191
     */
192
    public boolean isPartial() {
193
        return partial;
194
    }
195

    
196
    /**
197
     * @see #isPartial()
198
     */
199
    public void setPartial(boolean partial) {
200
        this.partial = partial;
201
    }
202

    
203

    
204
    public SynonymType getType() {
205
        return type;
206
    }
207

    
208
    public void setType(SynonymType type) {
209
        this.type = type;
210
        checkHomotypic();
211
    }
212

    
213

    
214
//***************** METHODS **************************/
215
	/**
216
	 * Returns true if <i>this</i> is a synonym of the given taxon.
217
	 *
218
	 * @param taxon	the taxon to check synonym for
219
	 * @return	true if <i>this</i> is a synonm of the given taxon
220
	 *
221
	 * @see #getAcceptedTaxon()
222
	 */
223
	@Transient
224
	public boolean isSynonymOf(Taxon taxon){
225
		return taxon != null && taxon.equals(this.acceptedTaxon);
226
	}
227

    
228
	@Override
229
    @Transient
230
	public boolean isOrphaned() {
231
	    return this.acceptedTaxon == null || this.acceptedTaxon.isOrphaned();
232
	}
233

    
234
    /**
235
     * Checks if the synonym type is homotypic. If it is
236
     * the name of <code>this</code> synonym is added to the {@link HomotypicalGroup
237
     * homotypic group} of the {@link Taxon accepted taxon}.
238
     */
239
    private void checkHomotypic() {
240
        if (type != null && type.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())
241
                && acceptedTaxon != null && acceptedTaxon.getName() != null){
242
                acceptedTaxon.getName().getHomotypicalGroup().addTypifiedName(this.getName());
243
        }
244
    }
245

    
246
//*********************** CLONE ********************************************************/
247

    
248
	@Override
249
	public Object clone() {
250
		Synonym result;
251
		result = (Synonym)super.clone();
252

    
253
		//no changes to accepted taxon, type, partial, proParte
254

    
255
		return result;
256

    
257
	}
258

    
259

    
260
}
(7-7/20)