some NOT NULLs and reverting taxonName.authorshipCache = empty
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / MediaKey.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.description;
11
12 import java.util.HashSet;
13 import java.util.Set;
14
15 import javax.persistence.Entity;
16 import javax.persistence.FetchType;
17 import javax.persistence.JoinColumn;
18 import javax.persistence.JoinTable;
19 import javax.persistence.ManyToMany;
20 import javax.persistence.OneToMany;
21 import javax.validation.constraints.NotNull;
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.XmlRootElement;
28 import javax.xml.bind.annotation.XmlSchemaType;
29 import javax.xml.bind.annotation.XmlType;
30
31 import org.apache.log4j.Logger;
32 import org.hibernate.annotations.Cascade;
33 import org.hibernate.annotations.CascadeType;
34 import org.hibernate.envers.Audited;
35 import org.hibernate.search.annotations.Indexed;
36
37 import eu.etaxonomy.cdm.model.common.Representation;
38 import eu.etaxonomy.cdm.model.location.NamedArea;
39 import eu.etaxonomy.cdm.model.media.Media;
40 import eu.etaxonomy.cdm.model.taxon.Taxon;
41
42 /**
43 * The class representing single-access fixed dichotomous or polytomous authored
44 * decision keys (as opposed to {@link FeatureTree multiple-access keys}) used to identify
45 * {@link SpecimenOrObservationBase specimens or observations} (this means to assign {@link Taxon taxa} to).
46 * The determination process is based on the tree structure of the key and on
47 * the statements of its leads.
48 *
49 * @author m.doering
50 * @version 1.0
51 * @created 08-Nov-2007 13:06:28
52 */
53
54 @XmlAccessorType(XmlAccessType.FIELD)
55 @XmlType(name = "MediaKey", propOrder = {
56 "coveredTaxa",
57 "taxonomicScope",
58 "geographicalScope",
59 "scopeRestrictions",
60 "keyRepresentations"
61 })
62 @XmlRootElement(name = "MediaKey")
63 @Entity
64 @Indexed(index = "eu.etaxonomy.cdm.model.media.Media")
65 @Audited
66 public class MediaKey extends Media implements IIdentificationKey{
67 private static final long serialVersionUID = -29095811051894471L;
68 @SuppressWarnings("unused")
69 private static final Logger logger = Logger.getLogger(MediaKey.class);
70
71 @XmlElementWrapper(name = "CoveredTaxa")
72 @XmlElement(name = "CoveredTaxon")
73 @XmlIDREF
74 @XmlSchemaType(name = "IDREF")
75 @ManyToMany(fetch = FetchType.LAZY)
76 @NotNull
77 private Set<Taxon> coveredTaxa = new HashSet<Taxon>();
78
79 @XmlElementWrapper( name = "GeographicalScope")
80 @XmlElement( name = "Area")
81 @XmlIDREF
82 @XmlSchemaType(name = "IDREF")
83 @ManyToMany(fetch = FetchType.LAZY)
84 @JoinTable(name="MediaKey_NamedArea")
85 @NotNull
86 private Set<NamedArea> geographicalScope = new HashSet<NamedArea>();
87
88 @XmlElementWrapper(name = "TaxonomicScope")
89 @XmlElement(name = "Taxon")
90 @XmlIDREF
91 @XmlSchemaType(name = "IDREF")
92 @ManyToMany(fetch = FetchType.LAZY)
93 @JoinTable(
94 name="MediaKey_Taxon",
95 joinColumns=@JoinColumn(name="mediaKey_id"),
96 inverseJoinColumns=@JoinColumn(name="taxon_id")
97 )
98 @NotNull
99 private Set<Taxon> taxonomicScope = new HashSet<Taxon>();
100
101 @XmlElementWrapper( name = "ScopeRestrictions")
102 @XmlElement( name = "Restriction")
103 @XmlIDREF
104 @XmlSchemaType(name = "IDREF")
105 @ManyToMany(fetch = FetchType.LAZY)
106 @JoinTable(name="MediaKey_Scope")
107 @NotNull
108 private Set<Scope> scopeRestrictions = new HashSet<Scope>();
109
110 @XmlElementWrapper( name = "KeyRepresentations")
111 @XmlElement( name = "KeyRepresentation")
112 @XmlIDREF
113 @XmlSchemaType(name = "IDREF")
114 @OneToMany(fetch=FetchType.LAZY, orphanRemoval=true)
115 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE,CascadeType.DELETE})
116 @NotNull
117 private Set<Representation> keyRepresentations = new HashSet<Representation>();
118
119 /**
120 * Class constructor: creates a new empty identification key instance.
121 */
122 protected MediaKey() {
123 super();
124 }
125
126 /**
127 * Creates a new empty identification key instance.
128 */
129 public static MediaKey NewInstance(){
130 return new MediaKey();
131 }
132
133
134 /**
135 * Returns the set of possible {@link Taxon taxa} corresponding to
136 * <i>this</i> identification key.
137 */
138 public Set<Taxon> getCoveredTaxa() {
139 if(coveredTaxa == null) {
140 this.coveredTaxa = new HashSet<Taxon>();
141 }
142 return coveredTaxa;
143 }
144 /**
145 * @see #getCoveredTaxa()
146 */
147 protected void setCoveredTaxa(Set<Taxon> coveredTaxa) {
148 this.coveredTaxa = coveredTaxa;
149 }
150
151 /**
152 * Adds a {@link Taxon taxa} to the set of {@link #getCoveredTaxa() covered taxa}
153 * corresponding to <i>this</i> identification key.
154 *
155 * @param taxon the taxon to be added to <i>this</i> identification key
156 * @see #getCoveredTaxa()
157 */
158 public void addCoveredTaxon(Taxon taxon) {
159 this.coveredTaxa.add(taxon);
160 }
161
162 /**
163 * Removes one element from the set of {@link #getCoveredTaxa() covered taxa}
164 * corresponding to <i>this</i> identification key.
165 *
166 * @param taxon the taxon which should be removed
167 * @see #getCoveredTaxa()
168 * @see #addCoveredTaxon(Taxon)
169 */
170 public void removeCoveredTaxon(Taxon taxon) {
171 this.coveredTaxa.remove(taxon);
172 }
173
174 /**
175 * Returns the set of {@link NamedArea named areas} indicating the geospatial
176 * data where <i>this</i> identification key is valid.
177 */
178 public Set<NamedArea> getGeographicalScope() {
179 if(geographicalScope == null) {
180 this.geographicalScope = new HashSet<NamedArea>();
181 }
182 return geographicalScope;
183 }
184
185 /**
186 * Adds a {@link NamedArea geoScope} to the set of {@link #getGeoScopes() geogspatial scopes}
187 * corresponding to <i>this</i> identification key.
188 *
189 * @param geoScope the named area to be added to <i>this</i> identification key
190 * @see #getGeoScopes()
191 */
192 public void addGeographicalScope(NamedArea geoScope) {
193 this.geographicalScope.add(geoScope);
194 }
195 /**
196 * Removes one element from the set of {@link #getGeoScopes() geogspatial scopes}
197 * corresponding to <i>this</i> identification key.
198 *
199 * @param geoScope the named area which should be removed
200 * @see #getGeoScopes()
201 * @see #addGeoScope(NamedArea)
202 */
203 public void removeGeographicalScope(NamedArea geoScope) {
204 this.geographicalScope.remove(geoScope);
205 }
206
207 /**
208 * Returns the set of {@link Taxon taxa} that define the taxonomic
209 * scope of <i>this</i> identification key
210 */
211 public Set<Taxon> getTaxonomicScope() {
212 if(taxonomicScope == null) {
213 this.taxonomicScope = new HashSet<Taxon>();
214 }
215 return taxonomicScope;
216 }
217
218 /**
219 * Adds a {@link Taxon taxa} to the set of {@link #getTaxonomicScope() taxonomic scopes}
220 * corresponding to <i>this</i> identification key.
221 *
222 * @param taxon the taxon to be added to <i>this</i> identification key
223 * @see #getTaxonomicScope()
224 */
225 public void addTaxonomicScope(Taxon taxon) {
226 this.taxonomicScope.add(taxon);
227 }
228
229 /**
230 * Removes one element from the set of {@link #getTaxonomicScope() taxonomic scopes}
231 * corresponding to <i>this</i> identification key.
232 *
233 * @param taxon the taxon which should be removed
234 * @see #getTaxonomicScope()
235 * @see #addTaxonomicScope(Taxon)
236 */
237 public void removeTaxonomicScope(Taxon taxon) {
238 this.taxonomicScope.remove(taxon);
239 }
240
241 /**
242 * Returns the set of {@link Representation key representations} corresponding to
243 * <i>this</i> identification key
244 */
245 public Set<Representation> getKeyRepresentations() {
246 if(keyRepresentations == null) {
247 this.keyRepresentations = new HashSet<Representation>();
248 }
249 return keyRepresentations;
250 }
251
252 /**
253 * Adds a {@link Representation key representation} to the set of {@link #getKeyRepresentations() key representations}
254 * corresponding to <i>this</i> identification key.
255 *
256 * @param keyRepresentation the key representation to be added to <i>this</i> identification key
257 * @see #getKeyRepresentations()
258 */
259 public void addKeyRepresentation(Representation keyRepresentation) {
260 this.keyRepresentations.add(keyRepresentation);
261 }
262
263 /**
264 * Removes one element from the set of {@link #getKeyRepresentations() key representations}
265 * corresponding to <i>this</i> identification key.
266 *
267 * @param keyRepresentation the key representation which should be removed
268 * @see #getKeyRepresentations()
269 * @see #addKeyRepresentation(Representation)
270 */
271 public void removeKeyRepresentation(Representation keyRepresentation) {
272 this.keyRepresentations.remove(keyRepresentation);
273 }
274
275 /**
276 * Returns the set of {@link Scope scope restrictions} corresponding to
277 * <i>this</i> identification key
278 */
279 public Set<Scope> getScopeRestrictions() {
280 if(scopeRestrictions == null) {
281 this.scopeRestrictions = new HashSet<Scope>();
282 }
283 return scopeRestrictions;
284 }
285
286 /**
287 * Adds a {@link Scope scope restriction} to the set of {@link #getScopeRestrictions() scope restrictions}
288 * corresponding to <i>this</i> identification key.
289 *
290 * @param scopeRestriction the scope restriction to be added to <i>this</i> identification key
291 * @see #getScopeRestrictions()
292 */
293 public void addScopeRestriction(Scope scopeRestriction) {
294 this.scopeRestrictions.add(scopeRestriction);
295 }
296
297 /**
298 * Removes one element from the set of {@link #getScopeRestrictions() scope restrictions}
299 * corresponding to <i>this</i> identification key.
300 *
301 * @param scopeRestriction the scope restriction which should be removed
302 * @see #getScopeRestrictions()
303 * @see #addScopeRestriction(Scope)
304 */
305 public void removeScopeRestriction(Scope scopeRestriction) {
306 this.scopeRestrictions.remove(scopeRestriction);
307 }
308
309 //*********************** CLONE ********************************************************/
310
311 /**
312 * Clones <i>this</i> MediaKey. This is a shortcut that enables to create
313 * a new instance that differs only slightly from <i>this</i> MediaKey by
314 * modifying only some of the attributes.
315 *
316 * @see eu.etaxonomy.cdm.model.media.Media#clone()
317 * @see java.lang.Object#clone()
318 */
319 @Override
320 public Object clone() {
321 MediaKey result;
322
323 try{
324 result = (MediaKey)super.clone();
325
326 result.coveredTaxa = new HashSet<Taxon>();
327 for (Taxon taxon: this.coveredTaxa){
328 result.addCoveredTaxon(taxon);
329 }
330
331 result.geographicalScope = new HashSet<NamedArea>();
332 for (NamedArea area: this.geographicalScope){
333 result.addGeographicalScope(area);
334 }
335
336 result.keyRepresentations = new HashSet<Representation>();
337 for (Representation rep: this.keyRepresentations) {
338 result.addKeyRepresentation(rep);
339 }
340
341 result.scopeRestrictions = new HashSet<Scope>();
342 for (Scope scope: this.scopeRestrictions){
343 result.addScopeRestriction(scope);
344 }
345
346 result.taxonomicScope = new HashSet<Taxon>();
347 for (Taxon taxon: this.taxonomicScope){
348 result.addTaxonomicScope(taxon);
349 }
350
351 return result;
352
353 }catch (CloneNotSupportedException e) {
354 logger.warn("Object does not implement cloneable");
355 e.printStackTrace();
356 return null;
357 }
358
359
360 }
361 }