Temporarily use getStrUuid method to annotate field uuid as XML ID until we migrate...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / taxon / Synonym.java
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 org.apache.log4j.Logger;
13 import org.hibernate.annotations.Cascade;
14 import org.hibernate.annotations.CascadeType;
15
16 import eu.etaxonomy.cdm.model.common.IRelated;
17 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
18 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
19
20 import java.util.*;
21
22 import javax.persistence.*;
23 import javax.xml.bind.annotation.XmlAccessType;
24 import javax.xml.bind.annotation.XmlAccessorType;
25 import javax.xml.bind.annotation.XmlElement;
26 import javax.xml.bind.annotation.XmlElementWrapper;
27 import javax.xml.bind.annotation.XmlIDREF;
28 import javax.xml.bind.annotation.XmlRootElement;
29 import javax.xml.bind.annotation.XmlSchemaType;
30 import javax.xml.bind.annotation.XmlType;
31
32 /**
33 * The class for synonyms: these are {@link TaxonBase taxa} the {@link name.TaxonNameBase taxon names}
34 * of which are not used by the {@link TaxonBase#getSec() reference} to designate a real
35 * taxon but are mentioned as taxon names that were oder are used by some other
36 * unspecified references to designate (at least to some extent) the same
37 * particular real taxon. Synonyms that are involved in no
38 * {@link SynonymRelationship synonym relationship} are actually meaningless.<BR>
39 * Splitting taxa in "accepted/correct" and "synonyms"
40 * makes it easier to handle particular relationships between
41 * ("accepted/correct") {@link Taxon taxa} on the one hand and between ("synonym") taxa
42 * and ("accepted/correct") taxa on the other.
43 *
44 * @author m.doering
45 * @version 1.0
46 * @created 08-Nov-2007 13:06:55
47 */
48 @XmlAccessorType(XmlAccessType.FIELD)
49 @XmlType(name = "Synonym", propOrder = {
50 "synonymRelations"
51 })
52 @XmlRootElement(name = "Synonym")
53 @Entity
54 public class Synonym extends TaxonBase implements IRelated<SynonymRelationship>{
55
56 static Logger logger = Logger.getLogger(Synonym.class);
57
58 //@XmlTransient
59 // Don't need the synonym relations here since they are stored at taxon side?
60 @XmlElementWrapper(name = "SynonymRelations")
61 @XmlElement(name = "SynonymRelationship")
62 @XmlIDREF
63 @XmlSchemaType(name = "IDREF")
64 private Set<SynonymRelationship> synonymRelations = new HashSet<SynonymRelationship>();
65
66 // ************* CONSTRUCTORS *************/
67 /**
68 * Class constructor: creates a new empty synonym instance.
69 *
70 * @see #Synonym(TaxonNameBase, ReferenceBase)
71 */
72 //TODO should be private, but still produces Spring init errors
73 public Synonym(){
74 }
75
76 /**
77 * Class constructor: creates a new synonym instance with
78 * the {@link name.TaxonNameBase taxon name} used and the {@link reference.ReferenceBase reference}
79 * using it as a synonym and not as an ("accepted/correct") {@link Taxon taxon}.
80 *
81 * @param taxonNameBase the taxon name used
82 * @param sec the reference using the taxon name
83 * @see Synonym#Synonym(TaxonNameBase, ReferenceBase)
84 */
85 public Synonym(TaxonNameBase taxonNameBase, ReferenceBase sec){
86 super(taxonNameBase, sec);
87 }
88
89 //********* METHODS **************************************/
90
91 /**
92 * Creates a new synonym instance with
93 * the {@link name.TaxonNameBase taxon name} used and the {@link reference.ReferenceBase reference}
94 * using it as a synonym and not as an ("accepted/correct") {@link Taxon taxon}.
95 *
96 * @param taxonNameBase the taxon name used
97 * @param sec the reference using the taxon name
98 * @see #Synonym(TaxonNameBase, ReferenceBase)
99 */
100 public static Synonym NewInstance(TaxonNameBase taxonName, ReferenceBase sec){
101 Synonym result = new Synonym(taxonName, sec);
102 return result;
103 }
104
105 /**
106 * Returns the set of all {@link SynonymRelationship synonym relationships}
107 * in which <i>this</i> synonym is involved. <i>This</i> synonym can only
108 * be the source within these synonym relationships.
109 *
110 * @see #addSynonymRelation(SynonymRelationship)
111 * @see #addRelationship(SynonymRelationship)
112 * @see #removeSynonymRelation(SynonymRelationship)
113 */
114 @OneToMany(mappedBy="relatedFrom", fetch=FetchType.LAZY)
115 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
116 public Set<SynonymRelationship> getSynonymRelations() {
117 return synonymRelations;
118 }
119 /**
120 * @see #getSynonymRelations()
121 * @see #addRelationship(SynonymRelationship)
122 */
123 protected void setSynonymRelations(Set<SynonymRelationship> synonymRelations) {
124 this.synonymRelations = synonymRelations;
125 }
126 /**
127 * Adds an existing {@link SynonymRelationship synonym relationship} to the set of
128 * {@link #getSynonymRelations() synonym relationships} assigned to <i>this</i> synonym. If
129 * the source of the synonym relationship does not match with <i>this</i>
130 * synonym no addition will be carried out.<BR>
131 * This methods does the same as the {@link #addRelationship() addRelationship} method.
132 *
133 * @param synonymRelation the synonym relationship to be added to <i>this</i> synonym's
134 * synonym relationships set
135 * @see #addRelationship(SynonymRelationship)
136 * @see #getSynonymRelations()
137 * @see #removeSynonymRelation(SynonymRelationship)
138 */
139 protected void addSynonymRelation(SynonymRelationship synonymRelation) {
140 this.synonymRelations.add(synonymRelation);
141 }
142 /**
143 * Removes one element from the set of {@link SynonymRelationship synonym relationships} assigned
144 * to <i>this</i> synonym. Due to bidirectionality the given
145 * synonym relationship will also be removed from the set of synonym
146 * relationships assigned to the {@link Taxon#getSynonymRelations() taxon} involved in the
147 * relationship. Furthermore the content of
148 * the {@link SynonymRelationship#getAcceptedTaxon() accepted taxon attribute} and of the
149 * {@link SynonymRelationship#getSynonym() synonym attribute} within the synonym relationship
150 * itself will be set to "null".
151 *
152 * @param synonymRelation the synonym relationship which should be deleted
153 * @see #getSynonymRelations()
154 * @see #addRelationship(SynonymRelationship)
155 * @see #removeSynonym(Synonym)
156 */
157 public void removeSynonymRelation(SynonymRelationship synonymRelation) {
158 synonymRelation.setSynonym(null);
159 Taxon taxon = synonymRelation.getAcceptedTaxon();
160 if (taxon != null){
161 synonymRelation.setAcceptedTaxon(null);
162 taxon.removeSynonymRelation(synonymRelation);
163 }
164 this.synonymRelations.remove(synonymRelation);
165 }
166
167
168 /**
169 * Adds an existing {@link SynonymRelationship synonym relationship} to the set of
170 * {@link #getSynonymRelations() synonym relationships} assigned to <i>this</i> synonym. If
171 * the source of the synonym relationship does not match with <i>this</i>
172 * synonym no addition will be carried out.<BR>
173 * This methods does the same as the {@link #addSynonymRelation() addSynonymRelation} method.
174 *
175 * @param synonymRelation the synonym relationship to be added to <i>this</i> synonym's
176 * synonym relationships set
177 * @see #addSynonymRelation(SynonymRelationship)
178 * @see #getSynonymRelations()
179 * @see #removeSynonymRelation(SynonymRelationship)
180 */
181 /* (non-Javadoc)
182 * @see eu.etaxonomy.cdm.model.common.IRelated#addRelationship(eu.etaxonomy.cdm.model.common.RelationshipBase)
183 */
184 public void addRelationship(SynonymRelationship rel){
185 addSynonymRelation(rel);
186 }
187
188
189 /**
190 * Returns the set of all ("accepted/correct") {@link Taxon taxa} involved in the same
191 * {@link SynonymRelationship synonym relationships} as <i>this</i> synonym.
192 * Each taxon is the target and <i>this</i> synonym is the source of a {@link SynonymRelationship synonym relationship}
193 * belonging to the {@link #getSynonymRelations() set of synonym relationships} assigned to
194 * <i>this</i> synonym. For a particular synonym there are more than one
195 * ("accepted/correct") taxon only if the {@link SynonymRelationship#isProParte() "is pro parte" flag}
196 * of the corresponding {@link SynonymRelationship synonym relationships} is set.
197 *
198 * @see #getSynonymRelations()
199 * @see #getRelationType(Taxon)
200 * @see SynonymRelationship#isProParte()
201 */
202 @Transient
203 public Set<Taxon> getAcceptedTaxa() {
204 Set<Taxon>taxa=new HashSet<Taxon>();
205 for (SynonymRelationship rel:getSynonymRelations()){
206 taxa.add(rel.getAcceptedTaxon());
207 }
208 return taxa;
209 }
210
211 /**
212 * Returns the set of {@link SynonymRelationshipType synonym relationship types} of the
213 * {@link SynonymRelationship synonym relationships} where the {@link SynonymRelationship#getSynonym() synonym}
214 * is <i>this</i> synonym and the {@link SynonymRelationship#getAcceptedTaxon() taxon}
215 * is the given one. "Null" is returned if the given taxon is "null" or if
216 * no synonym relationship exists from <i>this</i> synonym to the
217 * given taxon.
218 *
219 * @param taxon the ("accepted/correct") taxon to which a synonym relationship
220 * from <i>this</i> synonym should point
221 * @see #getSynonymRelations()
222 * @see #getAcceptedTaxa()
223 */
224 @Transient
225 public Set<SynonymRelationshipType> getRelationType(Taxon taxon){
226 Set<SynonymRelationshipType> result = new HashSet<SynonymRelationshipType>();
227 if (taxon == null ){
228 return result;
229 }
230 for (SynonymRelationship rel : getSynonymRelations()){
231 Taxon acceptedTaxon = rel.getAcceptedTaxon();
232 if (taxon.equals(acceptedTaxon)){
233 result.add(rel.getType());
234 }
235 }
236 return result;
237 }
238 }