Project

General

Profile

Download (9.2 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2007 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10

    
11
package eu.etaxonomy.cdm.model.description;
12

    
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.Set;
19
import java.util.Map.Entry;
20

    
21
import javax.persistence.Entity;
22
import javax.persistence.FetchType;
23
import javax.persistence.JoinColumn;
24
import javax.persistence.JoinTable;
25
import javax.persistence.ManyToMany;
26
import javax.persistence.ManyToOne;
27
import javax.persistence.OneToMany;
28
import javax.persistence.Transient;
29
import javax.validation.constraints.NotNull;
30
import javax.xml.bind.annotation.XmlAccessType;
31
import javax.xml.bind.annotation.XmlAccessorType;
32
import javax.xml.bind.annotation.XmlElement;
33
import javax.xml.bind.annotation.XmlElementWrapper;
34
import javax.xml.bind.annotation.XmlIDREF;
35
import javax.xml.bind.annotation.XmlRootElement;
36
import javax.xml.bind.annotation.XmlSchemaType;
37
import javax.xml.bind.annotation.XmlType;
38

    
39
import org.apache.log4j.Logger;
40
import org.hibernate.annotations.Cascade;
41
import org.hibernate.annotations.CascadeType;
42
import org.hibernate.envers.Audited;
43

    
44
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
45
import eu.etaxonomy.cdm.model.common.Language;
46
import eu.etaxonomy.cdm.model.common.LanguageString;
47
import eu.etaxonomy.cdm.model.common.Representation;
48

    
49
/**
50
 * 
51
 * The working set class allows the demarcation of a set of descriptions
52
 * associated with representations and a set of features and their
53
 * dependencies.
54
 * 
55
 * @author h.fradin
56
 * @created 12.08.2009
57
 * @version 1.0
58
 */
59

    
60
@XmlAccessorType(XmlAccessType.FIELD)
61
@XmlType(name = "WorkingSet", propOrder = {
62
    "representations",
63
    "descriptiveSystem",
64
    "descriptions"
65
})
66
@XmlRootElement(name = "WorkingSet")
67
@Entity
68
@Audited
69

    
70
public class WorkingSet extends AnnotatableEntity {
71
	private static final long serialVersionUID = 3256448866757415686L;
72
	private static final Logger logger = Logger.getLogger(WorkingSet.class);
73
	
74
	@XmlElementWrapper(name = "Representations")
75
	@XmlElement(name = "Representation")
76
    @OneToMany(fetch=FetchType.EAGER)
77
	@Cascade( { CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE })
78
	private Set<Representation> representations = new HashSet<Representation>();
79
	
80
	@XmlElement(name = "DescriptiveSystem")
81
	@XmlIDREF
82
	@XmlSchemaType(name = "IDREF")
83
	@ManyToOne(fetch = FetchType.LAZY)
84
	@Cascade({CascadeType.SAVE_UPDATE})
85
	private FeatureTree descriptiveSystem;
86
	
87
	@XmlElementWrapper(name = "Descriptions")
88
	@XmlElement(name = "Description")
89
    @XmlIDREF
90
    @XmlSchemaType(name = "IDREF")
91
    @ManyToMany(fetch = FetchType.LAZY)
92
    @JoinTable(
93
        name="WorkingSet_DescriptionBase",
94
        joinColumns=@JoinColumn(name="WorkingSet_id"),
95
        inverseJoinColumns=@JoinColumn(name="descriptions_id")
96
    )
97
	@Cascade(CascadeType.SAVE_UPDATE)
98
	@NotNull
99
	private Set<DescriptionBase> descriptions = new HashSet<DescriptionBase>();
100
	
101
	/** 
102
	 * Class constructor: creates a new empty working set instance.
103
	 */
104
	protected WorkingSet() {
105
		super();
106
	}
107
	
108
	/** 
109
	 * Creates a new empty working set instance.
110
	 */
111
	public static WorkingSet NewInstance(){
112
		return new WorkingSet();
113
	}
114
	
115
	public Set<Representation> getRepresentations() {
116
		return this.representations;
117
	}
118

    
119
	public void addRepresentation(Representation representation) {
120
		this.representations.add(representation);
121
	}
122

    
123
	public void removeRepresentation(Representation representation) {
124
		this.representations.remove(representation);
125
	}
126

    
127
	public Representation getRepresentation(Language lang) {
128
		for (Representation repr : representations){
129
			Language reprLanguage = repr.getLanguage();
130
			if (reprLanguage != null && reprLanguage.equals(lang)){
131
				return repr;
132
			}
133
		}
134
		return null;
135
	}
136
	
137
	/**
138
	 * @see #getPreferredRepresentation(Language)
139
	 * @param language
140
	 * @return
141
	 */
142
	public Representation getPreferredRepresentation(Language language) {
143
		Representation repr = getRepresentation(language); 
144
		if(repr == null){
145
			repr = getRepresentation(Language.DEFAULT());
146
		}
147
		if(repr == null){
148
			repr = getRepresentations().iterator().next();
149
		}
150
		return repr;
151
	}
152
	
153
	/**
154
	 * Returns the Representation in the preferred language. Preferred languages
155
	 * are specified by the parameter languages, which receives a list of
156
	 * Language instances in the order of preference. If no representation in
157
	 * any preferred languages is found the method falls back to return the
158
	 * Representation in Language.DEFAULT() and if necessary further falls back
159
	 * to return the first element found if any.
160
	 * 
161
	 * TODO think about this fall-back strategy & 
162
	 * see also {@link TextData#getPreferredLanguageString(List)}
163
	 * 
164
	 * @param languages
165
	 * @return
166
	 */
167
	public Representation getPreferredRepresentation(List<Language> languages) {
168
		Representation repr = null;
169
		if(languages != null){
170
			for(Language language : languages) {
171
				repr = getRepresentation(language); 
172
				if(repr != null){
173
					return repr;
174
				}
175
			}
176
		}
177
		if(repr == null){
178
			repr = getRepresentation(Language.DEFAULT());
179
		}
180
		if(repr == null){
181
			Iterator<Representation> it = getRepresentations().iterator();
182
			if(it.hasNext()){
183
				repr = getRepresentations().iterator().next();
184
			}
185
		}
186
		return repr;
187
	}
188
	
189
	@Transient
190
	public String getLabel() {
191
		if(getLabel(Language.DEFAULT())!=null){
192
			Representation repr = getRepresentation(Language.DEFAULT());
193
			return (repr == null)? null :repr.getLabel();
194
		}else{
195
			for (Representation r : representations){
196
				return r.getLabel();
197
			}			
198
		}
199
		return super.getUuid().toString();
200
	}
201
	
202
	public String getLabel(Language lang) {
203
		Representation repr = this.getRepresentation(lang);
204
		return (repr == null) ? null : repr.getLabel();
205
	}	
206
	
207
	public void setLabel(String label){
208
		Language lang = Language.DEFAULT();
209
		setLabel(label, lang);
210
	}
211

    
212
	public void setLabel(String label, Language language){
213
		if (language != null){
214
			Representation repr = getRepresentation(language);
215
			if (repr != null){
216
				repr.setLabel(label);
217
			}else{
218
				repr = Representation.NewInstance(null, label, null, language);
219
			}
220
			this.addRepresentation(repr);
221
		}
222
	}
223
	
224
	public FeatureTree getDescriptiveSystem() {
225
		return descriptiveSystem;
226
	}
227
	public void setDescriptiveSystem(FeatureTree descriptiveSystem) {
228
		this.descriptiveSystem = descriptiveSystem;
229
	}
230
	
231
	/**
232
	 * Returns the {@link DescriptionBase descriptions} of
233
	 * <i>this</i> working set.
234
	 * 
235
	 * @see    #addDescription(DescriptionBase)
236
	 * @see    #removeDescription(DescriptionBase)
237
	 */
238
	public Set<DescriptionBase> getDescriptions() {
239
		return descriptions;
240
	}
241
	
242
	/**
243
	 * Adds an existing {@link DescriptionBase description} to the set of
244
	 * {@link #getDescriptions() descriptions} of <i>this</i>
245
	 * working set.
246
	 * 
247
	 * @param description	the description to be added to <i>this</i> working set
248
	 * @see    	   			#getDescriptions()
249
	 * @see    	   			WorkingSet#addDescription(DescriptionBase)
250
	 */
251
	public boolean addDescription(DescriptionBase description) {
252
		boolean result = this.descriptions.add(description);
253
		if (! description.getWorkingSets().contains(this)){
254
			description.addWorkingSet(this);
255
		}
256
		return result;
257
	}
258
	
259
	/** 
260
	 * Removes one element from the set of {@link #getDescriptions() descriptions} involved
261
	 * in <i>this</i> working set.<BR>
262
	 *
263
	 * @param  description	the description which should be removed
264
	 * @see     		 	#getDescriptions()
265
	 * @see     		  	#addDescription(DescriptionBase)
266
	 * @see     		  	WorkingSet#removeDescription(DescriptionBase)
267
	 */
268
	public boolean removeDescription(DescriptionBase description) {
269
		boolean result = this.descriptions.remove(description);
270
		if (description.getWorkingSets().contains(this)){
271
			description.removeWorkingSet(this);
272
		}
273
		return result;
274
	}
275
	
276
	//*********************** CLONE ********************************************************/
277
	
278
	/** 
279
	 * Clones <i>this</i> WorkingSet. This is a shortcut that enables to create
280
	 * a new instance that differs only slightly from <i>this</i> WorkingSet by
281
	 * modifying only some of the attributes.
282
	 * The descriptions and the descriptive system are the same, the representations 
283
	 * are cloned.
284
	 * 
285
	 * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
286
	 * @see java.lang.Object#clone()
287
	 */
288
	@Override
289
	public Object clone() {
290
		WorkingSet result;
291
		try {
292
			result = (WorkingSet)super.clone();
293
			result.descriptions = new HashSet<DescriptionBase>();
294
			
295
			for (DescriptionBase desc: this.descriptions){
296
				result.addDescription(desc);
297
			}
298
			
299
			result.representations = new HashSet<Representation>();
300
			for (Representation rep : this.representations){
301
				result.addRepresentation((Representation)rep.clone());
302
			}
303
			
304
			return result;
305
		}catch (CloneNotSupportedException e) {
306
			logger.warn("Object does not implement cloneable");
307
			e.printStackTrace();
308
			return null;
309
		}
310
	}
311
	
312
}
(38-38/40)