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