(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.Collection;
14 import java.util.Collections;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Set;
18
19 import javax.persistence.Entity;
20 import javax.persistence.FetchType;
21 import javax.persistence.OneToMany;
22 import javax.persistence.Transient;
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.XmlType;
28
29 import org.apache.log4j.Logger;
30 import org.hibernate.annotations.Cascade;
31 import org.hibernate.annotations.CascadeType;
32
33 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
34 import eu.etaxonomy.cdm.model.occurrence.Specimen;
35 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
36 import eu.etaxonomy.cdm.model.taxon.Synonym;
37 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
38 import eu.etaxonomy.cdm.model.taxon.TaxonComparator;
39 import eu.etaxonomy.cdm.strategy.cache.name.INameCacheStrategy;
40
41
42 /**
43 * The homotypical group class represents a set of {@link TaxonNameBase taxon names} all sharing
44 * the same type specimens. It can also include names with a {@link common.Rank rank} higher
45 * than "species aggregate" like genera or families which usually are typified by
46 * a taxon name that finally (a name type designation can also point to another
47 * taxon name) points to a species name, which in turn is typified by a (set of)
48 * physical type specimen(s). This class allows to define a
49 * {@link SpecimenTypeDesignation specimen type designation} only once
50 * for the homotypical group instead of defining a type designation for each one
51 * of the taxon names subsumed under one homotypical group.
52 *
53 * @author m.doering
54 * @version 1.0
55 * @created 08-Nov-2007
56 */
57 @XmlAccessorType(XmlAccessType.FIELD)
58 @XmlType(name = "HomotypicalGroup", propOrder = {
59 "typifiedNames",
60 "typeDesignations"
61 })
62 @Entity
63 public class HomotypicalGroup extends AnnotatableEntity {
64 static Logger logger = Logger.getLogger(HomotypicalGroup.class);
65
66 @XmlElementWrapper(name = "TypifiedNames")
67 @XmlElement(name = "TypifiedName")
68 protected Set<TaxonNameBase> typifiedNames = new HashSet();
69
70 @XmlElementWrapper(name = "TypeDesignations")
71 @XmlElement(name = "TypeDesignation")
72 protected Set<SpecimenTypeDesignation> typeDesignations = new HashSet();
73
74 /**
75 * Class constructor: creates a new homotypical group instance with an
76 * empty set of typified {@link TaxonNameBase taxon names} and an empty set of
77 * {@link SpecimenTypeDesignation specimen type designations}.
78 */
79 public HomotypicalGroup() {
80 super();
81 }
82
83 /**
84 * Creates a new homotypical group instance with an empty set of typified
85 * {@link TaxonNameBase taxon names} and an empty set of
86 * {@link SpecimenTypeDesignation specimen type designations}.
87 *
88 * @see #HomotypicalGroup()
89 */
90 public static HomotypicalGroup NewInstance(){
91 return new HomotypicalGroup();
92 }
93
94
95
96 /**
97 * Returns the set of {@link TaxonNameBase taxon names} that belong to this homotypical group.
98 *
99 * @see #getTypeDesignations()
100 */
101 @OneToMany(mappedBy="homotypicalGroup", fetch=FetchType.LAZY)
102 public Set<TaxonNameBase> getTypifiedNames() {
103 return typifiedNames;
104 }
105 /**
106 * @see #getTypifiedNames()
107 */
108 protected void setTypifiedNames(Set<TaxonNameBase> typifiedNames) {
109 this.typifiedNames = typifiedNames;
110 }
111 /**
112 * Adds a new {@link TaxonNameBase taxon name} to the set of taxon names that belong
113 * to this homotypical group and to the corresponding set of each
114 * {@link SpecimenTypeDesignation#getTypifiedNames() type designation}
115 * associated with this homotypical group.
116 *
117 * @param typifiedName the taxon name to be added to this group
118 * @see #getTypifiedNames()
119 * @see #removeTypifiedName(TaxonNameBase)
120 */
121 public void addTypifiedName(TaxonNameBase typifiedName) {
122 if (typifiedName != null){
123 typifiedName.setHomotypicalGroup(this);
124 typifiedNames.add(typifiedName);
125 }
126 }
127 /**
128 * Removes one element from the set of {@link TaxonNameBase taxon names}
129 * that belong to this homotypical group.
130 *
131 * @param taxonBase the taxon name which should be removed from the corresponding set
132 * @see #addTypifiedName(TaxonNameBase)
133 */
134 public void removeTypifiedName(TaxonNameBase typifiedName) {
135 typifiedName.setHomotypicalGroup(null);
136 typifiedNames.remove(typifiedName);
137 }
138
139 /**
140 * Merges the typified {@link TaxonNameBase taxon names} from one homotypical group into
141 * the set of typified taxon names of this homotypical group.
142 *
143 * @param homotypicalGroupToMerge the homotypical group the typified names of which
144 * are to be transferred to this homotypical group
145 */
146 public void merge(HomotypicalGroup homotypicalGroupToMerge){
147 if (homotypicalGroupToMerge != null){
148 Set<TaxonNameBase> typifiedNames = new HashSet<TaxonNameBase>();
149 typifiedNames.addAll(homotypicalGroupToMerge.getTypifiedNames());
150 for (TaxonNameBase typifiedName: typifiedNames){
151 this.addTypifiedName(typifiedName);
152 }
153 }
154 }
155
156
157 /**
158 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} that
159 * typify this homotypical group including the status of these designations.
160 *
161 * @see #getTypifiedNames()
162 */
163 @OneToMany
164 @Cascade({CascadeType.SAVE_UPDATE})
165 public Set<SpecimenTypeDesignation> getTypeDesignations() {
166 return typeDesignations;
167 }
168 /**
169 * @see #getTypeDesignations()
170 */
171 protected void setTypeDesignations(Set<SpecimenTypeDesignation> typeDesignations) {
172 this.typeDesignations = typeDesignations;
173 }
174 /**
175 * Adds a new {@link SpecimenTypeDesignation specimen type designation} to the set
176 * of specimen type designations assigned to this homotypical group and eventually
177 * (with a boolean parameter) also to the corresponding set of each of the
178 * {@link TaxonNameBase taxon names} belonging to this homotypical group.
179 *
180 * @param typeDesignation the specimen type designation to be added
181 * @param addToAllNames the boolean flag indicating whether the addition will also
182 * carried out for each taxon name
183 *
184 * @see TaxonNameBase#getSpecimenTypeDesignations()
185 * @see SpecimenTypeDesignation
186 */
187 public void addTypeDesignation(SpecimenTypeDesignation typeDesignation, boolean addToAllNames) {
188 if (typeDesignation != null){
189 typeDesignation.setHomotypicalGroup(this);
190 typeDesignations.add(typeDesignation);
191 }
192 if (addToAllNames){
193 for (TaxonNameBase taxonNameBase : this.typifiedNames){
194 taxonNameBase.addSpecimenTypeDesignation(typeDesignation);
195 }
196 }
197 }
198 /**
199 * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
200 * {@link HomotypicalGroup homotypical group} to which this {@link TaxonNameBase taxon name} belongs.
201 * The same element will be removed from the corresponding set of each of
202 * the taxon names belonging to this homotypical group. Furthermore the
203 * homotypical group attribute of the specimen type designation will be
204 * nullified.
205 *
206 * @param typeDesignation the specimen type designation which should be deleted
207 * @see #getTypeDesignations()
208 * @see #addTypeDesignation(SpecimenTypeDesignation, boolean)
209 * @see TaxonNameBase#removeSpecimenTypeDesignation(SpecimenTypeDesignation)
210 * @see SpecimenTypeDesignation#getHomotypicalGroup()
211 */
212 public void removeTypeDesignation(SpecimenTypeDesignation typeDesignation) {
213 if (typeDesignation != null){
214 typeDesignation.setHomotypicalGroup(null);
215 typeDesignations.remove(typeDesignation);
216 }
217 for (TaxonNameBase taxonNameBase : this.typifiedNames){
218 taxonNameBase.removeSpecimenTypeDesignation(typeDesignation);
219 }
220 }
221
222
223 /**
224 * Retrieves the ordered list of {@link taxon.Synonym synonyms} (according to a given reference)
225 * the {@link TaxonNameBase taxon names} of which belong to this homotypical group.
226 * If other names are part of this group that are not considered synonyms
227 * according to the respective reference, then they will not be included in
228 * the result set.
229 *
230 * @param sec the reference whose treatment is to be considered
231 * @return the ordered list of synonyms
232 * @see taxon.Synonym
233 * @see TaxonNameBase#getSynonyms()
234 * @see TaxonNameBase#getTaxa()
235 */
236 @Transient
237 public List<Synonym> getSynonymsInGroup(ReferenceBase sec){
238 List<Synonym> result = new ArrayList();
239 for (TaxonNameBase<TaxonNameBase, INameCacheStrategy> n:this.getTypifiedNames()){
240 for (Synonym s:n.getSynonyms()){
241 if ( (s.getSec() == null && sec == null) ||
242 s.getSec().equals(sec)){
243 result.add(s);
244 }
245 }
246 }
247 //TODO test
248 Collections.sort(result, new TaxonComparator());
249 return result;
250 }
251 }