Project

General

Profile

Download (6.97 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.logging.log4j.LogManager;import org.apache.logging.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.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.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.TaxonName 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
 * @since 08-Nov-2007 13:06:55
54
 */
55
@XmlAccessorType(XmlAccessType.FIELD)
56
@XmlType(name = "Synonym", propOrder = {
57
    "acceptedTaxon",
58
    "type",
59
})
60
@XmlRootElement(name = "Synonym")
61
@Entity
62
@Indexed(index = "eu.etaxonomy.cdm.model.taxon.TaxonBase")
63
@Audited
64
@Configurable
65
@HomotypicSynonymsShouldBelongToGroup(groups = Level3.class)
66
public class Synonym extends TaxonBase<ITaxonCacheStrategy<Synonym>> {
67

    
68
    private static final long serialVersionUID = 6977221584815363620L;
69

    
70
    @SuppressWarnings("unused")
71
	private static final Logger logger = LogManager.getLogger(Synonym.class);
72

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

    
83
    @XmlElement(name = "Type")
84
    @XmlIDREF
85
    @XmlSchemaType(name = "IDREF")
86
    @ManyToOne(fetch=FetchType.EAGER)
87
    private SynonymType type;
88

    
89
//************************************* FACTORY ****************************/
90
    /**
91
     * @see #NewInstance(TaxonName, Reference)
92
     * @param taxonName
93
     * @param sec
94
     * @return
95
     */
96
    public static Synonym NewInstance(ITaxonNameBase taxonName, Reference sec){
97
        return NewInstance(TaxonName.castAndDeproxy(taxonName), sec);
98
    }
99

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

    
114
    public static Synonym NewInstance(TaxonName taxonName, Reference sec, String secDetail){
115
        Synonym result = new Synonym(taxonName, sec, secDetail);
116
        return result;
117
    }
118

    
119
// ********************* CONSTRUCTORS ******************************/
120

    
121
	/**
122
	 * Class constructor: creates a new empty synonym instance.
123
	 *
124
	 * @see 	#Synonym(TaxonName, Reference)
125
	 */
126
	//TODO should be private, but still produces Spring init errors
127
	public Synonym(){}
128

    
129
	private Synonym(TaxonName taxonName, Reference sec, String secDetail){
130
		super(taxonName, sec, secDetail);
131
	}
132

    
133
//********************** GETTER/SETTER ******************************/
134

    
135
	/**
136
	 * Returns the "accepted/valid" {@link Taxon taxon}
137
	 *
138
	 */
139
	public Taxon getAcceptedTaxon() {
140
		return this.acceptedTaxon;
141
	}
142
    protected void setAcceptedTaxon(Taxon acceptedTaxon) {
143
        if (acceptedTaxon == null){
144
            Taxon oldTaxon = this.acceptedTaxon;
145
            this.acceptedTaxon = null;
146
            oldTaxon.removeSynonym(this);
147
        }else{
148
            if (this.acceptedTaxon != null){
149
                this.acceptedTaxon.removeSynonym(this, false);
150
            }
151
            this.acceptedTaxon = acceptedTaxon;
152
            this.acceptedTaxon.addSynonym(this);
153
            checkHomotypic();
154
        }
155
    }
156

    
157
    public SynonymType getType() {
158
        return type;
159
    }
160
    public void setType(SynonymType type) {
161
        this.type = type;
162
        checkHomotypic();
163
    }
164

    
165
//***************** METHODS **************************/
166
	/**
167
	 * Returns true if <i>this</i> is a synonym of the given taxon.
168
	 *
169
	 * @param taxon	the taxon to check synonym for
170
	 * @return	true if <i>this</i> is a synonm of the given taxon
171
	 *
172
	 * @see #getAcceptedTaxon()
173
	 */
174
	@Transient
175
	public boolean isSynonymOf(Taxon taxon){
176
		return taxon != null && taxon.equals(this.acceptedTaxon);
177
	}
178

    
179
	@Override
180
    @Transient
181
	public boolean isOrphaned() {
182
	    return this.acceptedTaxon == null || this.acceptedTaxon.isOrphaned();
183
	}
184

    
185
    /**
186
     * Checks if the synonym type is homotypic. If it is
187
     * the name of <code>this</code> synonym is added to the {@link HomotypicalGroup
188
     * homotypic group} of the {@link Taxon accepted taxon}.
189
     */
190
    private void checkHomotypic() {
191
        if (type != null && type.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())
192
                && acceptedTaxon != null && acceptedTaxon.getName() != null){
193
                acceptedTaxon.getName().getHomotypicalGroup().addTypifiedName(this.getName());
194
        }
195
    }
196

    
197
//*********************** CLONE ********************************************************/
198

    
199
	@Override
200
	public Synonym clone() {
201
		Synonym result;
202
		result = (Synonym)super.clone();
203

    
204
		//no changes to accepted taxon, type, partial, proParte
205

    
206
		return result;
207

    
208
	}
209

    
210

    
211
}
(8-8/21)