Project

General

Profile

Download (15.4 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.List;
14
import java.util.Map;
15

    
16
import javax.persistence.Entity;
17
import javax.persistence.FetchType;
18
import javax.persistence.ManyToOne;
19
import javax.persistence.MapKeyJoinColumn;
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.Field;
38
import org.hibernate.search.annotations.FieldBridge;
39
import org.hibernate.search.annotations.Indexed;
40
import org.hibernate.search.annotations.Store;
41

    
42
import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;
43
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
44
import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
45
import eu.etaxonomy.cdm.model.common.Language;
46
import eu.etaxonomy.cdm.model.common.LanguageString;
47
import eu.etaxonomy.cdm.model.common.MultilanguageTextHelper;
48
import eu.etaxonomy.cdm.model.common.TermBase;
49

    
50

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

    
77
    //@XmlElement(name = "MultiLanguageText", type = MultilanguageText.class)
78
    @XmlElement(name = "MultiLanguageText")
79
    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
80
    @OneToMany (fetch= FetchType.LAZY, orphanRemoval=true)
81
    @MapKeyJoinColumn(name="multilanguagetext_mapkey_id")
82
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE})
83
    @Field(name="text", store=Store.YES)
84
    @FieldBridge(impl=MultilanguageTextFieldBridge.class)
85
    @NotNull
86
    private Map<Language, LanguageString> multilanguageText = new HashMap<Language,LanguageString>();
87

    
88
    @XmlElement(name = "Format")
89
    @XmlIDREF
90
    @XmlSchemaType(name = "IDREF")
91
    @ManyToOne(fetch = FetchType.LAZY)
92
    private TextFormat format;
93

    
94
    @XmlTransient
95
    @Transient
96
    private boolean isHashMapHibernateBugFixed = false;
97

    
98
    // ************* CONSTRUCTORS *************/
99
    /**
100
     * Class constructor: creates a new empty text data instance.
101
     *
102
     * @see #TextData(Feature)
103
     */
104
    public TextData(){
105
        this(null);
106
    }
107

    
108
    /**
109
     * Class constructor: creates a new text data instance with the {@link Feature feature}
110
     * to be described.
111
     *
112
     * @param	feature	the feature the text data refer to
113
     * @see 			#TextData()
114
     */
115
    public TextData(Feature feature){
116
        super(feature);
117
    }
118

    
119
    //********* METHODS **************************************/
120
    /**
121
     * Creates a new empty text data instance.
122
     *
123
     * @see #NewInstance(Feature)
124
     * @see #NewInstance(String, Language, TextFormat)
125
     * @see	#NewInstance(Feature, String, Language, TextFormat)
126
     */
127
    public static TextData NewInstance(){
128
        return new TextData();
129
    }
130

    
131
    /**
132
     * Creates a new text data instance with the {@link Feature feature}
133
     * to be described.
134
     *
135
     * @param	feature	the feature the text data refer to
136
     * @see 			#NewInstance()
137
     * @see 			#NewInstance(String, Language, TextFormat)
138
     * @see					#NewInstance(Feature, String, Language, TextFormat)
139
     */
140
    public static TextData NewInstance(Feature feature){
141
        return new TextData(feature);
142
    }
143

    
144
    /**
145
     * Creates a new text data instance with a given text in a given particular
146
     * {@link Language language} and with the given text format for structuring it.
147
     *
148
     * @param	text		the text string with the content of the description
149
     * @param	language	the language in which the text string is formulated
150
     * @param	format		the text format used to structure the text string
151
     * @see 				#NewInstance()
152
     * @see 				#NewInstance(Feature)
153
     * @see					#NewInstance(Feature, String, Language, TextFormat)
154
     */
155
    public static TextData NewInstance(String text, Language language, TextFormat format){
156
        TextData result =  new TextData();
157
        result.putText(language, text);
158
        result.setFormat(format);
159
        return result;
160
    }
161

    
162

    
163
    /**
164
     * Creates a new text data instance with a given text in a given particular
165
     * {@link Language language} and with the given text format for structuring it.
166
     *
167
     * @param   feature	    the feature the text data refer to
168
     * @param	text		the text string with the content of the description
169
     * @param	language	the language in which the text string is formulated
170
     * @param	format		the text format used to structure the text string
171
     * @see 				#NewInstance()
172
     * @see 				#NewInstance(Feature)
173
     * @see					#NewInstance(String, Language, TextFormat)
174
     */
175
    public static TextData NewInstance(Feature feature, String text, Language language, TextFormat format){
176
        TextData result =  new TextData(feature);
177
        result.putText(language, text);
178
        result.setFormat(format);
179
        return result;
180
    }
181

    
182
    /**
183
     * Returns a copy of the multilanguage text with the content of <i>this</i> text data.
184
     * The different {@link LanguageString language strings} (texts) contained in the
185
     * multilanguage text should all have the same meaning.
186
     *
187
     * @see	#getText(Language)
188
     */
189
    public Map<Language, LanguageString> getMultilanguageText() {
190
        fixHashMapHibernateBug();
191

    
192
//    	HashMap<Language, LanguageString> result = new HashMap<Language, LanguageString>();
193
//		result.putAll(multilanguageText);
194
//		return result;
195
        return multilanguageText;
196
    }
197

    
198
//    /**
199
//     * Sets the multilanguage text.
200
//	 * The different {@link LanguageString language strings} (texts) contained in the
201
//	 * multilanguage text should all have the same meaning.
202
//     *
203
//     * @param multilanguageText
204
//     */
205
//    private void setMultilanguageText(Map<Language,LanguageString> multilanguageText) {
206
//    	this.multilanguageText = multilanguageText;
207
//    }
208

    
209
    /**
210
     * Returns the multilanguage text with the content of <i>this</i> text data for
211
     * a specific language.
212
     *
213
     * @param language the language in which the text string looked for is formulated
214
     * @return
215
     */
216
    public LanguageString getLanguageText(Language language){
217
        //work around for the problem that contains does not work correctly in persisted maps.
218
        //This is because the persisted uuid is not present when loading the map key and
219
        //therefore the hash code for language is not computed correctly
220
        //see DescriptionElementDaoHibernateTest and #2114
221
//    	for (Map.Entry<Language, LanguageString> entry : multilanguageText.entrySet()){
222
//    		if (entry.getKey() != null){
223
//        		if (entry.getKey().equals(language)){
224
//        			return entry.getValue();
225
//        		}
226
//    		}else{
227
//    			if (language == null){
228
//    				return entry.getValue();
229
//    			}
230
//    		}
231
//    	}
232
//    	return null;
233
        //old
234
        return getMultilanguageText().get(language);
235
    }
236

    
237
    /**
238
     * Returns the text string in the given {@link Language language} with the content
239
     * of <i>this</i> text data.
240
     *
241
     * @param language	the language in which the text string looked for is formulated
242
     * @see				#getMultilanguageText(Language)
243
     */
244
    public String getText(Language language) {
245
        LanguageString languageString = getLanguageText(language);
246
        if (languageString == null){
247
            return null;
248
        }else{
249
            return languageString.getText();
250
        }
251
    }
252

    
253
    /**
254
     * Returns the LanguageString in the preferred language. Preferred languages
255
     * are specified by the parameter languages, which receives a list of
256
     * Language instances in the order of preference. If no representation in
257
     * any preferred languages is found the method falls back to return the
258
     * Representation in Language.DEFAULT() and if neccesary further falls back
259
     * to return the first element found if any.
260
     *
261
     * TODO think about this fall-back strategy &
262
     * see also {@link TermBase#getPreferredRepresentation(List)}
263
     *
264
     * @param languages
265
     * @return
266
     */
267
    public LanguageString getPreferredLanguageString(List<Language> languages) {
268
        return MultilanguageTextHelper.getPreferredLanguageString(getMultilanguageText(), languages);
269
    }
270

    
271
    private void fixHashMapHibernateBug() {
272
        //workaround for key problem
273
        if(! isHashMapHibernateBugFixed){
274
            HashMap<Language, LanguageString> tmp = new HashMap<Language, LanguageString>();
275
            tmp.putAll(multilanguageText);
276
            multilanguageText.clear();
277
            multilanguageText.putAll(tmp);
278

    
279
            isHashMapHibernateBugFixed = true;
280
        }
281
    }
282

    
283

    
284
    /**
285
     * Creates a {@link LanguageString language string} based on the given text string
286
     * and the given {@link Language language}, returns it and adds it to the multilanguage
287
     * text representing the content of <i>this</i> text data.
288
     *
289
     * @param language	the language in which the text string is formulated
290
     * @param text		the string representing the content of the text data
291
     * 					in a particular language
292
     *
293
     * @see    	   		#getMultilanguageText()
294
     * @see    	   		#putText(LanguageString)
295
     * @return			the previous language string associated with the given Language, or null if there was no mapping for the given Language
296
     */
297
    public LanguageString putText(Language language, String text) {
298
        fixHashMapHibernateBug();
299
        //** end workaround
300
        LanguageString languageString = multilanguageText.get(language);
301
        if (languageString != null){
302
            languageString.setText(text);
303
        }else{
304
            languageString = LanguageString.NewInstance(text, language);
305
        }
306
        this.multilanguageText.put(language , languageString);
307
        return languageString;
308
    }
309

    
310

    
311
    /**
312
     * Adds a translated {@link LanguageString text in a particular language}
313
     * to the multi-language text representing the content of <i>this</i> text data.
314
     * The given language string will be returned.
315
     *
316
     * @param languageString	the language string representing the content of
317
     * 							the text data in a particular language
318
     * @see    	   				#getMultilanguageText()
319
     * @see    	   				#putText(String, Language)
320
     * @see						HashMap#put(Object, Object)
321
     * @return					the previous language string associated with key, or null if there was no mapping for key
322
     */
323
    public LanguageString putText(LanguageString languageString) {
324

    
325
        if (languageString == null){
326
            return null;
327
        }else{
328
            Language language = languageString.getLanguage();
329
            return this.multilanguageText.put(language, languageString);
330
        }
331
    }
332
    /**
333
     * Removes from the multilanguage representing the content of
334
     * <i>this</i> text data the one {@link LanguageString language string}
335
     * with the given {@link Language language}. Returns the removed
336
     * language string.
337
     *
338
     * @param  language	the language in which the language string to be removed
339
     * 					has been formulated
340
     * @return			the language string associated with the given language or null if there was no mapping for the given Language
341
     * @see     		#getMultilanguageText()
342
     */
343
    public LanguageString removeText(Language language) {
344
        fixHashMapHibernateBug();
345
        return this.multilanguageText.remove(language);
346
    }
347

    
348
    /**
349
     * Returns the number of {@link Language languages} in which the content
350
     * of <i>this</i> text data has been formulated.
351
     *
352
     * @see	#getMultilanguageText()
353
     */
354
    public int countLanguages(){
355
        return multilanguageText.size();
356
    }
357

    
358

    
359
    /**
360
     * Returns the {@link TextFormat format} used for structuring the text representing
361
     * the content of <i>this</i> text data.
362
     *
363
     * @see	#getMultilanguageText()
364
     */
365
    public TextFormat getFormat() {
366
        return format;
367
    }
368
    /**
369
     * @see	#getFormat()
370
     */
371
    public void setFormat(TextFormat format) {
372
        this.format = format;
373
    }
374

    
375
    /**
376
     * @see {@link java.util.Map#containsKey(Object)}
377
     * @param language
378
     * @return
379
     */
380
    public boolean containsKey(Language language){
381
        return getMultilanguageText().containsKey(language);
382
    }
383

    
384
    /**
385
     * @see {@link java.util.Map#containsValue(Object)}
386
     * @param languageString
387
     * @return
388
     */
389
    public boolean containsValue(LanguageString languageString){
390
        return getMultilanguageText().containsValue(languageString);
391
    }
392

    
393

    
394
    /**
395
     * Returns the number of languages available for this text data.
396
     * @see {@link java.util.Map#size()}
397
     * @return
398
     */
399
    public int size(){
400
        return this.multilanguageText.size();
401
    }
402

    
403

    
404
//*********************************** CLONE *****************************************/
405

    
406
    /**
407
     * Clones <i>this</i> text data. This is a shortcut that enables to create
408
     * a new instance that differs only slightly from <i>this</i> text data by
409
     * modifying only some of the attributes.
410
     *
411
     * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
412
     * @see java.lang.Object#clone()
413
     */
414
    @Override
415
    public Object clone() {
416

    
417
        try {
418
            TextData result = (TextData)super.clone();
419

    
420
            //description
421
            result.multilanguageText = new HashMap<Language, LanguageString>();
422
            for (Language language : getMultilanguageText().keySet()){
423
                //TODO clone needed? See also IndividualsAssociation
424
                LanguageString newLanguageString = (LanguageString)getMultilanguageText().get(language).clone();
425
                result.multilanguageText.put(language, newLanguageString);
426
            }
427

    
428
            return result;
429
            //no changes to: format
430
        } catch (CloneNotSupportedException e) {
431
            logger.warn("Object does not implement cloneable");
432
            e.printStackTrace();
433
            return null;
434
        }
435
    }
436

    
437
}
(32-32/36)