Project

General

Profile

Download (15.3 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
@XmlAccessorType(XmlAccessType.FIELD)
64
@XmlType(name = "TextData", propOrder = {
65
    "multilanguageText",
66
    "format"
67
})
68
@XmlRootElement(name = "TextData")
69
@Entity
70
@Audited
71
@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionElementBase")
72
public class TextData extends DescriptionElementBase implements IMultiLanguageTextHolder, Cloneable{
73
    private static final long serialVersionUID = -2165015581278282615L;
74
    private static final Logger logger = Logger.getLogger(TextData.class);
75

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

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

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

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

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

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

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

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

    
161

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

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

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

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

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

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

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

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

    
278
            isHashMapHibernateBugFixed = true;
279
        }
280
    }
281

    
282

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

    
309

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

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

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

    
357

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

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

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

    
392

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

    
402

    
403
//*********************************** CLONE *****************************************/
404

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

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

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

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

    
436
}
(32-32/36)