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