2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.description
;
12 import java
.util
.HashSet
;
13 import java
.util
.Iterator
;
14 import java
.util
.List
;
17 import javax
.persistence
.Entity
;
18 import javax
.persistence
.FetchType
;
19 import javax
.persistence
.JoinTable
;
20 import javax
.persistence
.ManyToMany
;
21 import javax
.persistence
.ManyToOne
;
22 import javax
.persistence
.OneToMany
;
23 import javax
.persistence
.Transient
;
24 import javax
.validation
.constraints
.NotNull
;
25 import javax
.xml
.bind
.annotation
.XmlAccessType
;
26 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
27 import javax
.xml
.bind
.annotation
.XmlElement
;
28 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
29 import javax
.xml
.bind
.annotation
.XmlIDREF
;
30 import javax
.xml
.bind
.annotation
.XmlRootElement
;
31 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
32 import javax
.xml
.bind
.annotation
.XmlType
;
34 import org
.apache
.log4j
.Logger
;
35 import org
.hibernate
.annotations
.Cascade
;
36 import org
.hibernate
.annotations
.CascadeType
;
37 import org
.hibernate
.envers
.Audited
;
39 import eu
.etaxonomy
.cdm
.model
.common
.AnnotatableEntity
;
40 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
41 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
42 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
43 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
44 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
48 * The working set class allows the demarcation of a set of descriptions
49 * associated with representations and a set of features and their
56 @XmlAccessorType(XmlAccessType
.FIELD
)
57 @XmlType(name
= "WorkingSet", propOrder
= {
62 @XmlRootElement(name
= "WorkingSet")
66 public class WorkingSet
extends AnnotatableEntity
{
67 private static final long serialVersionUID
= 3256448866757415686L;
68 private static final Logger logger
= Logger
.getLogger(WorkingSet
.class);
70 @XmlElementWrapper(name
= "Representations")
71 @XmlElement(name
= "Representation")
72 @OneToMany(fetch
=FetchType
.EAGER
)
73 @Cascade( { CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
74 private Set
<Representation
> representations
= new HashSet
<>();
76 @XmlElement(name
= "DescriptiveSystem")
78 @XmlSchemaType(name
= "IDREF")
79 @ManyToOne(fetch
= FetchType
.LAZY
)
80 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
81 private FeatureTree descriptiveSystem
;
83 @XmlElementWrapper(name
= "Descriptions")
84 @XmlElement(name
= "Description")
86 @XmlSchemaType(name
= "IDREF")
87 @ManyToMany(fetch
= FetchType
.LAZY
)
88 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
90 private Set
<DescriptionBase
> descriptions
= new HashSet
<>();
92 @XmlElementWrapper(name
= "SubtreeTaxonFilter")
93 @XmlElement(name
= "Subtree")
95 @XmlSchemaType(name
= "IDREF")
96 @ManyToMany(fetch
= FetchType
.LAZY
)
97 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
99 //a positive filter that defines that all taxa in the subtree belong to
100 //the dataset. If the filter is NOT set, taxa need to be explicitly defined
101 //via the descriptions set. If the filter is set all taxa not having
102 //a description in descriptions yet are considered to have an empty description
103 //TODO what, if a taxon is removed from the subtree but a description exists in
105 private Set
<TaxonNode
> taxonSubtreeFilter
= new HashSet
<>();
107 @XmlElementWrapper(name
= "GeoFilter")
108 @XmlElement(name
= "FilteredArea")
110 @XmlSchemaType(name
= "IDREF")
111 @ManyToMany(fetch
= FetchType
.LAZY
)
112 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
113 @JoinTable(name
="WorkingSet_NamedArea")
115 private Set
<NamedArea
> geoFilter
= new HashSet
<>();
117 @XmlElement(name
= "minRank")
119 @XmlSchemaType(name
= "IDREF")
120 @ManyToOne(fetch
= FetchType
.LAZY
)
121 private Rank minRank
;
123 @XmlElement(name
= "maxRank")
125 @XmlSchemaType(name
= "IDREF")
126 @ManyToOne(fetch
= FetchType
.LAZY
)
127 private Rank maxRank
;
129 // ******************* FACTORY *********************************************/
131 public static WorkingSet
NewInstance(){
132 return new WorkingSet();
136 // *******************CONSTRUCTOR **********************************/
138 * Class constructor: creates a new empty working set instance.
140 protected WorkingSet() {
144 // ******************** GETTER / SETTER ************************/
147 public Set
<TaxonNode
> getTaxonSubtreeFilter() {
148 return taxonSubtreeFilter
;
151 //make public if needed
152 private void setTaxonSubtreeFilter(Set
<TaxonNode
> taxonSubtreeFilter
) {
153 this.taxonSubtreeFilter
= taxonSubtreeFilter
;
156 public void addTaxonSubtree(TaxonNode subtree
) {
157 this.taxonSubtreeFilter
.add(subtree
);
160 public void removeTaxonSubtree(TaxonNode subtree
) {
161 this.taxonSubtreeFilter
.remove(subtree
);
165 public Set
<NamedArea
> getGeoFilter() {
168 public void setGeoFilter(Set
<NamedArea
> geoFilter
) {
169 this.geoFilter
= geoFilter
;
171 public void addGeoFilterArea(NamedArea area
){
172 this.geoFilter
.add(area
);
174 public boolean removeGeoFilterArea(NamedArea area
) {
175 return this.geoFilter
.remove(area
);
179 public Rank
getMinRank() {
182 public void setMinRank(Rank minRank
) {
183 this.minRank
= minRank
;
187 public Rank
getMaxRank() {
190 public void setMaxRank(Rank maxRank
) {
191 this.maxRank
= maxRank
;
195 public Set
<Representation
> getRepresentations() {
196 return this.representations
;
198 public void addRepresentation(Representation representation
) {
199 this.representations
.add(representation
);
201 public void removeRepresentation(Representation representation
) {
202 this.representations
.remove(representation
);
205 public Representation
getRepresentation(Language lang
) {
206 for (Representation repr
: representations
){
207 Language reprLanguage
= repr
.getLanguage();
208 if (reprLanguage
!= null && reprLanguage
.equals(lang
)){
216 * @see #getPreferredRepresentation(Language)
220 public Representation
getPreferredRepresentation(Language language
) {
221 Representation repr
= getRepresentation(language
);
223 repr
= getRepresentation(Language
.DEFAULT());
226 repr
= getRepresentations().iterator().next();
232 * Returns the Representation in the preferred language. Preferred languages
233 * are specified by the parameter languages, which receives a list of
234 * Language instances in the order of preference. If no representation in
235 * any preferred languages is found the method falls back to return the
236 * Representation in Language.DEFAULT() and if necessary further falls back
237 * to return the first element found if any.
239 * TODO think about this fall-back strategy &
240 * see also {@link TextData#getPreferredLanguageString(List)}
245 public Representation
getPreferredRepresentation(List
<Language
> languages
) {
246 Representation repr
= null;
247 if(languages
!= null){
248 for(Language language
: languages
) {
249 repr
= getRepresentation(language
);
256 repr
= getRepresentation(Language
.DEFAULT());
259 Iterator
<Representation
> it
= getRepresentations().iterator();
261 repr
= getRepresentations().iterator().next();
268 public String
getLabel() {
269 if(getLabel(Language
.DEFAULT())!=null){
270 Representation repr
= getRepresentation(Language
.DEFAULT());
271 return (repr
== null)?
null :repr
.getLabel();
273 for (Representation r
: representations
){
277 return super.getUuid().toString();
280 public String
getLabel(Language lang
) {
281 Representation repr
= this.getRepresentation(lang
);
282 return (repr
== null) ?
null : repr
.getLabel();
285 public void setLabel(String label
){
286 Language lang
= Language
.DEFAULT();
287 setLabel(label
, lang
);
290 public void setLabel(String label
, Language language
){
291 if (language
!= null){
292 Representation repr
= getRepresentation(language
);
294 repr
.setLabel(label
);
296 repr
= Representation
.NewInstance(null, label
, null, language
);
298 this.addRepresentation(repr
);
302 public FeatureTree
getDescriptiveSystem() {
303 return descriptiveSystem
;
305 public void setDescriptiveSystem(FeatureTree descriptiveSystem
) {
306 this.descriptiveSystem
= descriptiveSystem
;
310 * Returns the {@link DescriptionBase descriptions} of
311 * <i>this</i> working set.
313 * @see #addDescription(DescriptionBase)
314 * @see #removeDescription(DescriptionBase)
316 public Set
<DescriptionBase
> getDescriptions() {
321 * Adds an existing {@link DescriptionBase description} to the set of
322 * {@link #getDescriptions() descriptions} of <i>this</i>
325 * @param description the description to be added to <i>this</i> working set
326 * @see #getDescriptions()
327 * @see WorkingSet#addDescription(DescriptionBase)
329 public boolean addDescription(DescriptionBase description
) {
330 boolean result
= this.descriptions
.add(description
);
331 if (! description
.getWorkingSets().contains(this)){
332 description
.addWorkingSet(this);
338 * Removes one element from the set of {@link #getDescriptions() descriptions} involved
339 * in <i>this</i> working set.<BR>
341 * @param description the description which should be removed
342 * @see #getDescriptions()
343 * @see #addDescription(DescriptionBase)
344 * @see WorkingSet#removeDescription(DescriptionBase)
346 public boolean removeDescription(DescriptionBase description
) {
347 boolean result
= this.descriptions
.remove(description
);
348 if (description
.getWorkingSets().contains(this)){
349 description
.removeWorkingSet(this);
354 //*********************** CLONE ********************************************************/
357 * Clones <i>this</i> WorkingSet. This is a shortcut that enables to create
358 * a new instance that differs only slightly from <i>this</i> WorkingSet by
359 * modifying only some of the attributes.
360 * The descriptions and the descriptive system are the same, the representations
363 * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
364 * @see java.lang.Object#clone()
367 public Object
clone() {
370 result
= (WorkingSet
)super.clone();
373 result
.descriptions
= new HashSet
<>();
374 for (DescriptionBase
<?
> desc
: this.descriptions
){
375 result
.addDescription(desc
);
379 result
.representations
= new HashSet
<>();
380 for (Representation rep
: this.representations
){
381 result
.addRepresentation((Representation
)rep
.clone());
385 result
.taxonSubtreeFilter
= new HashSet
<>();
386 for (TaxonNode subtree
: this.taxonSubtreeFilter
){
387 result
.addTaxonSubtree(subtree
);
391 result
.geoFilter
= new HashSet
<>();
392 for (NamedArea area
: this.geoFilter
){
393 result
.addGeoFilterArea(area
);
397 }catch (CloneNotSupportedException e
) {
398 logger
.warn("Object does not implement cloneable");