Project

General

Profile

Download (14 KB) Statistics
| Branch: | Tag: | Revision:
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.HashMap;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Map;
16

    
17
import javax.persistence.Entity;
18
import javax.persistence.FetchType;
19
import javax.persistence.ManyToOne;
20
import javax.persistence.OneToMany;
21
import javax.persistence.Transient;
22
import javax.validation.constraints.NotNull;
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.XmlIDREF;
27
import javax.xml.bind.annotation.XmlRootElement;
28
import javax.xml.bind.annotation.XmlSchemaType;
29
import javax.xml.bind.annotation.XmlTransient;
30
import javax.xml.bind.annotation.XmlType;
31
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
32

    
33
import org.apache.log4j.Logger;
34
import org.hibernate.annotations.Cascade;
35
import org.hibernate.annotations.CascadeType;
36
import org.hibernate.envers.Audited;
37
import org.hibernate.search.annotations.Indexed;
38
import org.hibernate.search.annotations.IndexedEmbedded;
39

    
40
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
41
import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
42
import eu.etaxonomy.cdm.model.common.Language;
43
import eu.etaxonomy.cdm.model.common.LanguageString;
44
import eu.etaxonomy.cdm.model.common.MultilanguageTextHelper;
45
import eu.etaxonomy.cdm.model.common.TermBase;
46

    
47

    
48
/**
49
 * This class represents information pieces expressed in one or several natural
50
 * languages (for the {@link Feature feature} "medical use" for instance).
51
 * A {@link TextFormat format} used for structuring the text may also be stated.
52
 * <P>
53
 * This class corresponds partially to NaturalLanguageDescriptionType according
54
 * to the SDD schema.
55
 *
56
 * @author m.doering
57
 * @version 1.0
58
 * @created 08-Nov-2007 13:06:59
59
 */
60
@XmlAccessorType(XmlAccessType.FIELD)
61
@XmlType(name = "TextData", propOrder = {
62
    "multilanguageText",
63
    "format"
64
})
65
@XmlRootElement(name = "TextData")
66
@Entity
67
@Audited
68
@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionElementBase")
69
public class TextData extends DescriptionElementBase implements IMultiLanguageTextHolder, Cloneable{
70
	private static final long serialVersionUID = -2165015581278282615L;
71
	private static final Logger logger = Logger.getLogger(TextData.class);
72

    
73
	//@XmlElement(name = "MultiLanguageText", type = MultilanguageText.class)
74
	@XmlElement(name = "MultiLanguageText")
75
    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
76
    @OneToMany (fetch= FetchType.LAZY)
77
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN })
78
    @IndexedEmbedded
79
    @NotNull
80
	private Map<Language, LanguageString> multilanguageText = new HashMap<Language,LanguageString>();
81
	
82
	@XmlElement(name = "Format")
83
	@XmlIDREF
84
	@XmlSchemaType(name = "IDREF")
85
	@ManyToOne(fetch = FetchType.LAZY)
86
	private TextFormat format;
87
	
88
	@XmlTransient
89
	@Transient
90
	private boolean isHashMapHibernateBugFixed = false;
91
	
92
	// ************* CONSTRUCTORS *************/	
93
	/** 
94
	 * Class constructor: creates a new empty text data instance.
95
	 * 
96
	 * @see #TextData(Feature)
97
	 */
98
	public TextData(){
99
		this(null);
100
	}
101
	
102
	/** 
103
	 * Class constructor: creates a new text data instance with the {@link Feature feature}
104
	 * to be described.
105
	 * 
106
	 * @param	feature	the feature the text data refer to
107
	 * @see 			#TextData()
108
	 */
109
	public TextData(Feature feature){
110
		super(feature);
111
	}
112
	
113
	//********* METHODS **************************************/
114
	/** 
115
	 * Creates a new empty text data instance.
116
	 * 
117
	 * @see #NewInstance(Feature)
118
	 * @see #NewInstance(String, Language, TextFormat)
119
	 */
120
	public static TextData NewInstance(){
121
		return new TextData();
122
	}
123
	
124
	/** 
125
	 * Creates a new text data instance with the {@link Feature feature}
126
	 * to be described.
127
	 * 
128
	 * @param	feature	the feature the text data refer to
129
	 * @see 			#NewInstance()
130
	 * @see 			#NewInstance(String, Language, TextFormat)
131
	 */
132
	public static TextData NewInstance(Feature feature){
133
		return new TextData(feature);
134
	}
135
	
136
	/** 
137
	 * Creates a new text data instance with a given text in a given particular
138
	 * {@link Language language} and with the given text format for structuring it.
139
	 * 
140
	 * @param	text		the text string with the content of the description 
141
	 * @param	language	the language in which the text string is formulated
142
	 * @param	format		the text format used to structure the text string
143
	 * @see 				#NewInstance()
144
	 * @see 				#NewInstance(Feature)
145
	 */
146
	public static TextData NewInstance(String text, Language language, TextFormat format){
147
		TextData result =  new TextData();
148
		result.putText(text, language);
149
		result.setFormat(format);
150
		return result;
151
	}
152

    
153
	/** 
154
	 * Returns a copy of the multilanguage text with the content of <i>this</i> text data. 
155
	 * The different {@link LanguageString language strings} (texts) contained in the
156
	 * multilanguage text should all have the same meaning.
157
	 * 
158
	 * @see	#getText(Language)
159
	 */
160
    public Map<Language, LanguageString> getMultilanguageText() {
161
		fixHashMapHibernateBug();
162
		
163
//    	HashMap<Language, LanguageString> result = new HashMap<Language, LanguageString>();
164
//		result.putAll(multilanguageText);
165
//		return result;
166
    	return multilanguageText;
167
	}
168
    
169
//    /**
170
//     * Sets the multilanguage text. 
171
//	 * The different {@link LanguageString language strings} (texts) contained in the
172
//	 * multilanguage text should all have the same meaning.
173
//     * 
174
//     * @param multilanguageText
175
//     */
176
//    private void setMultilanguageText(Map<Language,LanguageString> multilanguageText) {
177
//    	this.multilanguageText = multilanguageText;
178
//    }
179
    
180
    /**
181
     * Returns the multilanguage text with the content of <i>this</i> text data for
182
     * a specific language.
183
     * 
184
     * @param language the language in which the text string looked for is formulated
185
     * @return
186
     */
187
    public LanguageString getLanguageText(Language language){
188
    	//work around for the problem that contains does not work correctly in persisted maps.
189
    	//This is because the persisted uuid is not present when loading the map key and
190
    	//therefore the hash code for language is not computed correctly
191
    	//see DescriptionElementDaoHibernateTest and #2114
192
//    	for (Map.Entry<Language, LanguageString> entry : multilanguageText.entrySet()){
193
//    		if (entry.getKey() != null){
194
//        		if (entry.getKey().equals(language)){
195
//        			return entry.getValue();
196
//        		}
197
//    		}else{
198
//    			if (language == null){
199
//    				return entry.getValue();
200
//    			}
201
//    		}
202
//    	}
203
//    	return null;
204
    	//old
205
    	return getMultilanguageText().get(language);
206
    }
207
 
208
	/** 
209
	 * Returns the text string in the given {@link Language language} with the content
210
	 * of <i>this</i> text data.
211
	 * 
212
	 * @param language	the language in which the text string looked for is formulated
213
	 * @see				#getMultilanguageText(Language)
214
	 */ 
215
	public String getText(Language language) {
216
		LanguageString languageString = getLanguageText(language);
217
		if (languageString == null){
218
			return null;
219
		}else{
220
			return languageString.getText();
221
		}
222
	}
223
    
224
    /**
225
	 * Returns the LanguageString in the preferred language. Preferred languages
226
	 * are specified by the parameter languages, which receives a list of
227
	 * Language instances in the order of preference. If no representation in
228
	 * any preferred languages is found the method falls back to return the
229
	 * Representation in Language.DEFAULT() and if neccesary further falls back
230
	 * to return the first element found if any.
231
	 * 
232
	 * TODO think about this fall-back strategy & 
233
	 * see also {@link TermBase#getPreferredRepresentation(List)}
234
	 * 
235
	 * @param languages
236
	 * @return
237
	 */
238
	public LanguageString getPreferredLanguageString(List<Language> languages) {
239
		return MultilanguageTextHelper.getPreferredLanguageString(getMultilanguageText(), languages);
240
	}
241

    
242
	private void fixHashMapHibernateBug() {
243
		//workaround for key problem
244
		if(! isHashMapHibernateBugFixed){
245
			HashMap<Language, LanguageString> tmp = new HashMap<Language, LanguageString>();
246
			tmp.putAll(multilanguageText);
247
			multilanguageText.clear();
248
			multilanguageText.putAll(tmp);
249

    
250
			isHashMapHibernateBugFixed = true;
251
		}
252
	}
253
	
254
	/**
255
	 * Creates a {@link LanguageString language string} based on the given text string
256
	 * and the given {@link Language language}, returns it and adds it to the multilanguage 
257
	 * text representing the content of <i>this</i> text data.
258
	 * 
259
	 * @param text		the string representing the content of the text data
260
	 * 					in a particular language
261
	 * @param language	the language in which the text string is formulated
262
	 * @see    	   		#getMultilanguageText()
263
	 * @see    	   		#putText(LanguageString)
264
	 * @return			the previous language string associated with the given Language, or null if there was no mapping for the given Language
265
	 * @deprecated		should follow the put semantic of maps, this method will be removed in v4.0
266
	 * 					Use the {@link #putText(Language, String) putText} method instead
267
	 */
268
	public LanguageString putText(String text, Language language) {
269
		return this.putText(language, text);
270
	}
271
	
272
	/**
273
	 * Creates a {@link LanguageString language string} based on the given text string
274
	 * and the given {@link Language language}, returns it and adds it to the multilanguage 
275
	 * text representing the content of <i>this</i> text data.
276
	 * 
277
	 * @param language	the language in which the text string is formulated
278
	 * @param text		the string representing the content of the text data
279
	 * 					in a particular language
280
	 * 
281
	 * @see    	   		#getMultilanguageText()
282
	 * @see    	   		#putText(LanguageString)
283
	 * @return			the previous language string associated with the given Language, or null if there was no mapping for the given Language
284
	 */
285
	public LanguageString putText(Language language, String text) {
286
		fixHashMapHibernateBug();
287
		//** end workaround
288
		LanguageString languageString = multilanguageText.get(language);
289
		if (languageString != null){
290
			languageString.setText(text);
291
		}else{
292
			languageString = LanguageString.NewInstance(text, language);
293
		}
294
		LanguageString result = this.multilanguageText.put(language , languageString);
295
		return (result == null ? null : result);
296
	}
297

    
298
		
299
	/**
300
	 * Adds a translated {@link LanguageString text in a particular language}
301
	 * to the multi-language text representing the content of <i>this</i> text data.
302
	 * The given language string will be returned. 
303
	 * 
304
	 * @param languageString	the language string representing the content of
305
	 * 							the text data in a particular language
306
	 * @see    	   				#getMultilanguageText()
307
	 * @see    	   				#putText(String, Language)
308
	 * @see						HashMap#put(Object, Object)
309
	 * @return					the previous language string associated with key, or null if there was no mapping for key
310
	 */
311
	public LanguageString putText(LanguageString languageString) {
312
		
313
		if (languageString == null){
314
			return null;
315
		}else{
316
			Language language = languageString.getLanguage();
317
			return this.multilanguageText.put(language, languageString);
318
		}
319
	}
320
	/** 
321
	 * Removes from the multilanguage representing the content of
322
	 * <i>this</i> text data the one {@link LanguageString language string}
323
	 * with the given {@link Language language}. Returns the removed
324
	 * language string.
325
	 *
326
	 * @param  language	the language in which the language string to be removed
327
	 * 					has been formulated
328
	 * @return			the language string associated with the given language or null if there was no mapping for the given Language
329
	 * @see     		#getMultilanguageText()
330
	 */
331
	public LanguageString removeText(Language language) {
332
		fixHashMapHibernateBug();		
333
		return this.multilanguageText.remove(language);
334
	}
335
	
336
	/** 
337
	 * Returns the number of {@link Language languages} in which the content
338
	 * of <i>this</i> text data has been formulated.
339
	 * 
340
	 * @see	#getMultilanguageText()
341
	 */
342
	public int countLanguages(){
343
		return multilanguageText.size();
344
	}
345
	
346

    
347
	/** 
348
	 * Returns the {@link TextFormat format} used for structuring the text representing
349
	 * the content of <i>this</i> text data.
350
	 * 
351
	 * @see	#getMultilanguageText()
352
	 */
353
	public TextFormat getFormat() {
354
		return format;
355
	}
356
	/** 
357
	 * @see	#getFormat()
358
	 */
359
	public void setFormat(TextFormat format) {
360
		this.format = format;
361
	}
362
	
363
	/**
364
	 * @see {@link java.util.Map#containsKey(Object)}
365
	 * @param language
366
	 * @return
367
	 */
368
	public boolean containsKey(Language language){
369
		return getMultilanguageText().containsKey(language);
370
	}
371
	
372
	/**
373
	 * @see {@link java.util.Map#containsValue(Object)}
374
	 * @param languageString
375
	 * @return
376
	 */
377
	public boolean containsValue(LanguageString languageString){
378
		return getMultilanguageText().containsValue(languageString);
379
	}
380
	
381
	
382
	/**
383
	 * Returns the number of languages available for this text data.
384
	 * @see {@link java.util.Map#size()}
385
	 * @return
386
	 */
387
	public int size(){
388
		return this.multilanguageText.size();
389
	}
390

    
391

    
392
//*********************************** CLONE *****************************************/
393

    
394
	/** 
395
	 * Clones <i>this</i> text data. This is a shortcut that enables to create
396
	 * a new instance that differs only slightly from <i>this</i> text data by
397
	 * modifying only some of the attributes.
398
	 * 
399
	 * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
400
	 * @see java.lang.Object#clone()
401
	 */
402
	@Override
403
	public Object clone() {
404

    
405
		try {
406
			TextData result = (TextData)super.clone();
407

    
408
			//description
409
			result.multilanguageText = new HashMap<Language, LanguageString>();
410
			for (Language language : getMultilanguageText().keySet()){
411
				//TODO clone needed? See also IndividualsAssociation
412
				LanguageString newLanguageString = (LanguageString)getMultilanguageText().get(language).clone();
413
				result.multilanguageText.put(language, newLanguageString);
414
			}
415
			
416
			return result;
417
			//no changes to: format
418
		} catch (CloneNotSupportedException e) {
419
			logger.warn("Object does not implement cloneable");
420
			e.printStackTrace();
421
			return null;
422
		}
423
	}
424

    
425
}
(35-35/39)