problems with generics fixed & switched to aspectj 1.6.2 due to bugs in earlier versions
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / HomotypicalGroup.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.name;
11
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17
18 import javax.persistence.Entity;
19 import javax.persistence.FetchType;
20 import javax.persistence.OneToMany;
21 import javax.persistence.Transient;
22 import javax.xml.bind.annotation.XmlAccessType;
23 import javax.xml.bind.annotation.XmlAccessorType;
24 import javax.xml.bind.annotation.XmlElement;
25 import javax.xml.bind.annotation.XmlElementWrapper;
26 import javax.xml.bind.annotation.XmlIDREF;
27 import javax.xml.bind.annotation.XmlSchemaType;
28 import javax.xml.bind.annotation.XmlType;
29
30 import org.apache.log4j.Logger;
31 import org.hibernate.annotations.Cascade;
32 import org.hibernate.annotations.CascadeType;
33
34 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
35 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
36 import eu.etaxonomy.cdm.model.taxon.Synonym;
37 import eu.etaxonomy.cdm.model.taxon.TaxonComparator;
38 import eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy;
39
40
41 /**
42 * The homotypical group class represents a set of {@link TaxonNameBase taxon names} associated
43 * on the base of their typifications. Since it can be asserted that two taxon
44 * names are typified by the same type without mentioning the type itself, even
45 * taxon names without explicit {@link TypeDesignationBase type designation} can belong
46 * to an homotypical group.<BR>
47 * Taxon names belonging to an homotypical group and the taxon names or
48 * {@link eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase specimens} used as types for their
49 * {@link TypeDesignationBase type designations} have the following properties: <ul>
50 * <li> A taxon name belongs exactly to one homotypical group
51 * <li> A type specimen or a type name can be used as a type only for taxon
52 * names belonging to the same homotypical group<BR>
53 * - therefore an homotypical group circumscribes a set of types<BR>
54 * - each taxon name shares a subset of these types<BR>
55 * - each type is used by a subset of these taxon names
56 * within the homotypical group
57 * <li> Names that share at least one common type must belong to the same
58 * homotypical group
59 * <li> Names that share the same basionym or replaced synonym must belong to
60 * the same homotypical group
61 * </ul>
62 *
63 * @see TypeDesignationBase
64 * @see NameTypeDesignation
65 * @see SpecimenTypeDesignation
66 * @author m.doering
67 * @version 1.0
68 * @created 08-Nov-2007
69 */
70 @XmlAccessorType(XmlAccessType.FIELD)
71 @XmlType(name = "HomotypicalGroup", propOrder = {
72 "typifiedNames"
73 })
74 @Entity
75 public class HomotypicalGroup extends AnnotatableEntity {
76 static Logger logger = Logger.getLogger(HomotypicalGroup.class);
77
78 @XmlElementWrapper(name = "TypifiedNames")
79 @XmlElement(name = "TypifiedName")
80 @XmlIDREF
81 @XmlSchemaType(name = "IDREF")
82 protected Set<TaxonNameBase> typifiedNames = new HashSet<TaxonNameBase>();
83
84 /**
85 * Class constructor: creates a new homotypical group instance with an
86 * empty set of typified {@link TaxonNameBase taxon names}.
87 */
88 public HomotypicalGroup() {
89 super();
90 }
91
92 /**
93 * Creates a new homotypical group instance with an empty set of typified
94 * {@link TaxonNameBase taxon names}.
95 *
96 * @see #HomotypicalGroup()
97 */
98 public static HomotypicalGroup NewInstance(){
99 return new HomotypicalGroup();
100 }
101
102 /**
103 * Returns the set of {@link TaxonNameBase taxon names} that belong to <i>this</i> homotypical group.
104 *
105 * @see #getSpecimenTypeDesignations()
106 */
107 @OneToMany(mappedBy="homotypicalGroup", fetch=FetchType.LAZY)
108 public Set<TaxonNameBase> getTypifiedNames() {
109 return typifiedNames;
110 }
111 /**
112 * @see #getTypifiedNames()
113 */
114 protected void setTypifiedNames(Set<TaxonNameBase> typifiedNames) {
115 this.typifiedNames = typifiedNames;
116 }
117
118 /**
119 * Adds a new {@link TaxonNameBase taxon name} to the set of taxon names that belong
120 * to <i>this</i> homotypical group.
121 *
122 * @param typifiedName the taxon name to be added to <i>this</i> group
123 * @see #getTypifiedNames()
124 * @see #removeTypifiedName(TaxonNameBase)
125 */
126 public void addTypifiedName(TaxonNameBase typifiedName) {
127 if (typifiedName != null){
128 typifiedName.setHomotypicalGroup(this);
129 typifiedNames.add(typifiedName);
130 }
131 }
132 /**
133 * Removes one element from the set of {@link TaxonNameBase taxon names}
134 * that belong to <i>this</i> homotypical group.
135 *
136 * @param taxonBase the taxon name which should be removed from the corresponding set
137 * @see #addTypifiedName(TaxonNameBase)
138 */
139 public void removeTypifiedName(TaxonNameBase typifiedName) {
140 typifiedName.setHomotypicalGroup(null);
141 typifiedNames.remove(typifiedName);
142 }
143
144 /**
145 * Merges the typified {@link TaxonNameBase taxon names} from one homotypical group into
146 * the set of typified taxon names of <i>this</i> homotypical group.
147 *
148 * @param homotypicalGroupToMerge the homotypical group the typified names of which
149 * are to be transferred to <i>this</i> homotypical group
150 */
151 public void merge(HomotypicalGroup homotypicalGroupToMerge){
152 if (homotypicalGroupToMerge != null){
153 Set<TaxonNameBase> typifiedNames = new HashSet<TaxonNameBase>();
154 typifiedNames.addAll(homotypicalGroupToMerge.getTypifiedNames());
155 for (TaxonNameBase typifiedName: typifiedNames){
156 this.addTypifiedName(typifiedName);
157 }
158 }
159 }
160
161
162 /**
163 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} that
164 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
165 * including the status of these designations.
166 *
167 * @see #getTypifiedNames()
168 * @see #getNameTypeDesignations()
169 * @see #getTypeDesignations()
170 * @see TaxonNameBase#getSpecimenTypeDesignations()
171 */
172 @Transient
173 public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations(){
174 Set<SpecimenTypeDesignation> result = new HashSet<SpecimenTypeDesignation>();
175 for (TaxonNameBase taxonName : typifiedNames){
176 result.addAll(taxonName.getSpecimenTypeDesignations());
177 }
178 return result;
179 }
180
181 /**
182 * Returns the set of {@link NameTypeDesignation name type designations} that
183 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
184 * including the status of these designations.
185 *
186 * @see #getTypifiedNames()
187 * @see #getSpecimenTypeDesignations()
188 * @see #getTypeDesignations()
189 * @see TaxonNameBase#getNameTypeDesignations()
190 */
191 @Transient
192 public Set<NameTypeDesignation> getNameTypeDesignations(){
193 Set<NameTypeDesignation> result = new HashSet<NameTypeDesignation>();
194 for (TaxonNameBase taxonName : typifiedNames){
195 result.addAll(taxonName.getNameTypeDesignations());
196 }
197 return result;
198 }
199
200
201 /**
202 * Returns the set of all {@link TypeDesignationBase type designations} that
203 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
204 * (this includes either {@link NameTypeDesignation name type designations} or
205 * {@link SpecimenTypeDesignation specimen type designations}).
206 *
207 * @see #getTypifiedNames()
208 * @see #getNameTypeDesignations()
209 * @see #getSpecimenTypeDesignations()
210 * @see TaxonNameBase#getTypeDesignations()
211 */
212 @Transient
213 public Set<TypeDesignationBase> getTypeDesignations(){
214 Set<TypeDesignationBase> result = new HashSet<TypeDesignationBase>();
215 for (TaxonNameBase taxonName : typifiedNames){
216 result.addAll(taxonName.getTypeDesignations());
217 }
218 return result;
219 }
220
221 // /**
222 // * Returns the set of {@link SpecimenTypeDesignation specimen type designations} that
223 // * typify <i>this</i> homotypical group including the status of these designations.
224 // *
225 // * @see #getTypifiedNames()
226 // */
227 // @OneToMany
228 // @Cascade({CascadeType.SAVE_UPDATE})
229 // public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
230 // return specimenTypeDesignations;
231 // }
232 // /**
233 // * @see #getSpecimenTypeDesignations()
234 // */
235 // protected void setSpecimenTypeDesignations(Set<SpecimenTypeDesignation> specimenTypeDesignations) {
236 // this.specimenTypeDesignations = specimenTypeDesignations;
237 // }
238 // /**
239 // * Adds a new {@link SpecimenTypeDesignation specimen type designation} to the set
240 // * of specimen type designations assigned to <i>this</i> homotypical group and eventually
241 // * (with a boolean parameter) also to the corresponding set of each of the
242 // * {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group.
243 // *
244 // * @param specimenTypeDesignation the specimen type designation to be added
245 // * @param addToAllNames the boolean flag indicating whether the addition will also
246 // * carried out for each taxon name
247 // *
248 // * @see TaxonNameBase#getSpecimenTypeDesignations()
249 // * @see SpecimenTypeDesignation
250 // */
251 // public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation, boolean addToAllNames) {
252 // if (specimenTypeDesignation != null){
253 // specimenTypeDesignation.setHomotypicalGroup(this);
254 // specimenTypeDesignations.add(specimenTypeDesignation);
255 // }
256 // if (addToAllNames){
257 // for (TaxonNameBase taxonNameBase : this.typifiedNames){
258 // taxonNameBase.addSpecimenTypeDesignation(specimenTypeDesignation);
259 // }
260 // }
261 // }
262 // /**
263 // * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
264 // * {@link HomotypicalGroup homotypical group} to which this {@link TaxonNameBase taxon name} belongs.
265 // * The same element will be removed from the corresponding set of each of
266 // * the taxon names belonging to <i>this</i> homotypical group. Furthermore the
267 // * homotypical group attribute of the specimen type designation will be
268 // * nullified.
269 // *
270 // * @param specimenTypeDesignation the specimen type designation which should be deleted
271 // * @see #getSpecimenTypeDesignations()
272 // * @see #addSpecimenTypeDesignation(SpecimenTypeDesignation, boolean)
273 // * @see TaxonNameBase#removeSpecimenTypeDesignation(SpecimenTypeDesignation)
274 // * @see SpecimenTypeDesignation#getHomotypicalGroup()
275 // */
276 // public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation) {
277 // if (specimenTypeDesignation != null){
278 // specimenTypeDesignation.setHomotypicalGroup(null);
279 // specimenTypeDesignations.remove(specimenTypeDesignation);
280 // }
281 // for (TaxonNameBase taxonNameBase : this.typifiedNames){
282 // taxonNameBase.removeSpecimenTypeDesignation(specimenTypeDesignation);
283 // }
284 // }
285
286
287 // /**
288 // * Returns the set of {@link NameTypeDesignation name type designations} that
289 // * typify <i>this</i> homotypical group including the status of these designations.
290 // *
291 // * @see #getTypifiedNames()
292 // */
293 // @OneToMany
294 // @Cascade({CascadeType.SAVE_UPDATE})
295 // public Set<NameTypeDesignation> getNameTypeDesignations() {
296 // return nameTypeDesignations;
297 // }
298 // /**
299 // * @see #getNameTypeDesignations()
300 // */
301 // protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
302 // this.nameTypeDesignations = nameTypeDesignations;
303 // }
304 // /**
305 // * Adds a new {@link NameTypeDesignation name type designation} to the set
306 // * of name type designations assigned to <i>this</i> homotypical group and eventually
307 // * (with a boolean parameter) also to the corresponding set of each of the
308 // * {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group.
309 // *
310 // * @param nameTypeDesignation the name type designation to be added
311 // * @param addToAllNames the boolean flag indicating whether the addition will also
312 // * carried out for each taxon name
313 // *
314 // * @see TaxonNameBase#getNameTypeDesignations()
315 // * @see NameTypeDesignation
316 // */
317 // public void addNameTypeDesignation(NameTypeDesignation nameTypeDesignation, boolean addToAllNames) {
318 // if (nameTypeDesignation != null){
319 // nameTypeDesignation.setHomotypicalGroup(this);
320 // nameTypeDesignations.add(nameTypeDesignation);
321 // }
322 // if (addToAllNames){
323 // for (TaxonNameBase taxonNameBase : this.typifiedNames){
324 // taxonNameBase.addNameTypeDesignation(nameTypeDesignation);
325 // }
326 // }
327 // }
328 // /**
329 // * Removes one element from the set of {@link NameTypeDesignation name type designations} assigned to the
330 // * {@link HomotypicalGroup homotypical group} to which this {@link TaxonNameBase taxon name} belongs.
331 // * The same element will be removed from the corresponding set of each of
332 // * the taxon names belonging to <i>this</i> homotypical group. Furthermore the
333 // * homotypical group attribute of the name type designation will be
334 // * nullified.
335 // *
336 // * @param nameTypeDesignation the name type designation which should be deleted
337 // * @see #getNameTypeDesignations()
338 // * @see #addNameTypeDesignation(NameTypeDesignation, boolean)
339 // * @see TaxonNameBase#removeNameTypeDesignation(NameTypeDesignation)
340 // * @see NameTypeDesignation#getHomotypicalGroup()
341 // */
342 // public void removeNameTypeDesignation(NameTypeDesignation nameTypeDesignation) {
343 // if (nameTypeDesignation != null){
344 // nameTypeDesignation.setHomotypicalGroup(null);
345 // nameTypeDesignations.remove(nameTypeDesignation);
346 // }
347 // for (TaxonNameBase taxonNameBase : this.typifiedNames){
348 // taxonNameBase.removeNameTypeDesignation(nameTypeDesignation);
349 // }
350 // }
351
352
353 /**
354 * Retrieves the ordered list (depending on the date of publication) of
355 * {@link taxon.Synonym synonyms} (according to a given reference)
356 * the {@link TaxonNameBase taxon names} of which belong to <i>this</i> homotypical group.
357 * If other names are part of <i>this</i> group that are not considered synonyms
358 * according to the respective reference, then they will not be included in
359 * the result set.
360 *
361 * @param sec the reference whose treatment is to be considered
362 * @return the ordered list of synonyms
363 * @see TaxonNameBase#getSynonyms()
364 * @see TaxonNameBase#getTaxa()
365 * @see taxon.Synonym
366 */
367 @Transient
368 public List<Synonym> getSynonymsInGroup(ReferenceBase sec){
369 List<Synonym> result = new ArrayList();
370 for (TaxonNameBase<TaxonNameBase<? extends TaxonNameBase, ? extends INameCacheStrategy>, INameCacheStrategy> n:this.getTypifiedNames()){
371 for (Synonym s:n.getSynonyms()){
372 if ( (s.getSec() == null && sec == null) ||
373 s.getSec().equals(sec)){
374 result.add(s);
375 }
376 }
377 }
378 Collections.sort(result, new TaxonComparator());
379 return result;
380 }
381 }