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