root/trunk/cdmlib/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/description/TextData.java

Revision 13570, 15.0 kB (checked in by a.kohlbecker, 5 months ago)

harmonising whitespace tab->space

  • Property svn:keywords set to Id
Line 
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
10package eu.etaxonomy.cdm.model.description;
11
12import java.util.HashMap;
13import java.util.HashSet;
14import java.util.List;
15import java.util.Map;
16
17import javax.persistence.Entity;
18import javax.persistence.FetchType;
19import javax.persistence.ManyToOne;
20import javax.persistence.OneToMany;
21import javax.persistence.Transient;
22import javax.validation.constraints.NotNull;
23import javax.xml.bind.annotation.XmlAccessType;
24import javax.xml.bind.annotation.XmlAccessorType;
25import javax.xml.bind.annotation.XmlElement;
26import javax.xml.bind.annotation.XmlIDREF;
27import javax.xml.bind.annotation.XmlRootElement;
28import javax.xml.bind.annotation.XmlSchemaType;
29import javax.xml.bind.annotation.XmlTransient;
30import javax.xml.bind.annotation.XmlType;
31import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
32
33import org.apache.log4j.Logger;
34import org.hibernate.annotations.Cascade;
35import org.hibernate.annotations.CascadeType;
36import org.hibernate.envers.Audited;
37import org.hibernate.search.annotations.Indexed;
38import org.hibernate.search.annotations.IndexedEmbedded;
39
40import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
41import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
42import eu.etaxonomy.cdm.model.common.Language;
43import eu.etaxonomy.cdm.model.common.LanguageString;
44import eu.etaxonomy.cdm.model.common.MultilanguageTextHelper;
45import 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")
69public 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(language, text);
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    @Deprecated
269    public LanguageString putText(String text, Language language) {
270        return this.putText(language, text);
271    }
272
273    /**
274     * Creates a {@link LanguageString language string} based on the given text string
275     * and the given {@link Language language}, returns it and adds it to the multilanguage
276     * text representing the content of <i>this</i> text data.
277     *
278     * @param language  the language in which the text string is formulated
279     * @param text              the string representing the content of the text data
280     *                                  in a particular language
281     *
282     * @see                     #getMultilanguageText()
283     * @see                     #putText(LanguageString)
284     * @return                  the previous language string associated with the given Language, or null if there was no mapping for the given Language
285     */
286    public LanguageString putText(Language language, String text) {
287        fixHashMapHibernateBug();
288        //** end workaround
289        LanguageString languageString = multilanguageText.get(language);
290        if (languageString != null){
291            languageString.setText(text);
292        }else{
293            languageString = LanguageString.NewInstance(text, language);
294        }
295        LanguageString result = this.multilanguageText.put(language , languageString);
296        return (result == null ? null : result);
297    }
298
299
300    /**
301     * Adds a translated {@link LanguageString text in a particular language}
302     * to the multi-language text representing the content of <i>this</i> text data.
303     * The given language string will be returned.
304     *
305     * @param languageString    the language string representing the content of
306     *                                                  the text data in a particular language
307     * @see                                     #getMultilanguageText()
308     * @see                                     #putText(String, Language)
309     * @see                                             HashMap#put(Object, Object)
310     * @return                                  the previous language string associated with key, or null if there was no mapping for key
311     */
312    public LanguageString putText(LanguageString languageString) {
313
314        if (languageString == null){
315            return null;
316        }else{
317            Language language = languageString.getLanguage();
318            return this.multilanguageText.put(language, languageString);
319        }
320    }
321    /**
322     * Removes from the multilanguage representing the content of
323     * <i>this</i> text data the one {@link LanguageString language string}
324     * with the given {@link Language language}. Returns the removed
325     * language string.
326     *
327     * @param  language the language in which the language string to be removed
328     *                                  has been formulated
329     * @return                  the language string associated with the given language or null if there was no mapping for the given Language
330     * @see                     #getMultilanguageText()
331     */
332    public LanguageString removeText(Language language) {
333        fixHashMapHibernateBug();
334        return this.multilanguageText.remove(language);
335    }
336
337    /**
338     * Returns the number of {@link Language languages} in which the content
339     * of <i>this</i> text data has been formulated.
340     *
341     * @see     #getMultilanguageText()
342     */
343    public int countLanguages(){
344        return multilanguageText.size();
345    }
346
347
348    /**
349     * Returns the {@link TextFormat format} used for structuring the text representing
350     * the content of <i>this</i> text data.
351     *
352     * @see     #getMultilanguageText()
353     */
354    public TextFormat getFormat() {
355        return format;
356    }
357    /**
358     * @see     #getFormat()
359     */
360    public void setFormat(TextFormat format) {
361        this.format = format;
362    }
363
364    /**
365     * @see {@link java.util.Map#containsKey(Object)}
366     * @param language
367     * @return
368     */
369    public boolean containsKey(Language language){
370        return getMultilanguageText().containsKey(language);
371    }
372
373    /**
374     * @see {@link java.util.Map#containsValue(Object)}
375     * @param languageString
376     * @return
377     */
378    public boolean containsValue(LanguageString languageString){
379        return getMultilanguageText().containsValue(languageString);
380    }
381
382
383    /**
384     * Returns the number of languages available for this text data.
385     * @see {@link java.util.Map#size()}
386     * @return
387     */
388    public int size(){
389        return this.multilanguageText.size();
390    }
391
392
393//*********************************** CLONE *****************************************/
394
395    /**
396     * Clones <i>this</i> text data. This is a shortcut that enables to create
397     * a new instance that differs only slightly from <i>this</i> text data by
398     * modifying only some of the attributes.
399     *
400     * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
401     * @see java.lang.Object#clone()
402     */
403    @Override
404    public Object clone() {
405
406        try {
407            TextData result = (TextData)super.clone();
408
409            //description
410            result.multilanguageText = new HashMap<Language, LanguageString>();
411            for (Language language : getMultilanguageText().keySet()){
412                //TODO clone needed? See also IndividualsAssociation
413                LanguageString newLanguageString = (LanguageString)getMultilanguageText().get(language).clone();
414                result.multilanguageText.put(language, newLanguageString);
415            }
416
417            return result;
418            //no changes to: format
419        } catch (CloneNotSupportedException e) {
420            logger.warn("Object does not implement cloneable");
421            e.printStackTrace();
422            return null;
423        }
424    }
425
426}
Note: See TracBrowser for help on using the browser.