Project

General

Profile

Download (19.8 KB) Statistics
| Branch: | Tag: | Revision:
1 9479da48 Andreas Müller
/**
2
* Copyright (C) 2007 EDIT
3 22a09e94 Andreas Kohlbecker
* European Distributed Institute of Taxonomy
4 9479da48 Andreas Müller
* http://www.e-taxonomy.eu
5 22a09e94 Andreas Kohlbecker
*
6 9479da48 Andreas Müller
* 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
13 2beb45d7 ben.clark
import java.util.ArrayList;
14 fd7ee7b1 ben.clark
import java.util.HashMap;
15
import java.util.HashSet;
16 2beb45d7 ben.clark
import java.util.List;
17 fd7ee7b1 ben.clark
import java.util.Map;
18
import java.util.Set;
19 9479da48 Andreas Müller
20 fd7ee7b1 ben.clark
import javax.persistence.Entity;
21
import javax.persistence.FetchType;
22
import javax.persistence.Inheritance;
23
import javax.persistence.InheritanceType;
24
import javax.persistence.JoinTable;
25
import javax.persistence.ManyToMany;
26
import javax.persistence.ManyToOne;
27 a13c5f66 Andreas Müller
import javax.persistence.MapKeyJoinColumn;
28 fd7ee7b1 ben.clark
import javax.persistence.OneToMany;
29 3dd6c00e Andreas Müller
import javax.persistence.OrderColumn;
30 e9829ef9 Andreas Müller
import javax.persistence.Transient;
31 0ae18eec a.babadshanjan
import javax.xml.bind.annotation.XmlAccessType;
32
import javax.xml.bind.annotation.XmlAccessorType;
33
import javax.xml.bind.annotation.XmlElement;
34
import javax.xml.bind.annotation.XmlElementWrapper;
35 6cce5702 a.babadshanjan
import javax.xml.bind.annotation.XmlIDREF;
36
import javax.xml.bind.annotation.XmlSchemaType;
37 e9829ef9 Andreas Müller
import javax.xml.bind.annotation.XmlTransient;
38 0ae18eec a.babadshanjan
import javax.xml.bind.annotation.XmlType;
39 6cce5702 a.babadshanjan
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
40 9479da48 Andreas Müller
41 fd7ee7b1 ben.clark
import org.apache.log4j.Logger;
42
import org.hibernate.annotations.Cascade;
43
import org.hibernate.annotations.CascadeType;
44 3dd6c00e Andreas Müller
import org.hibernate.annotations.ListIndexBase;
45 fd7ee7b1 ben.clark
import org.hibernate.envers.Audited;
46
import org.hibernate.search.annotations.IndexedEmbedded;
47
48
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
49 6b4e491d Andreas Müller
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
50 533cbb43 Andreas Müller
import eu.etaxonomy.cdm.model.common.DefinedTerm;
51 e49a769c n.hoffmann
import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
52 fad74844 Andreas Müller
import eu.etaxonomy.cdm.model.common.IOriginalSource;
53 57606ee3 Andreas Müller
import eu.etaxonomy.cdm.model.common.ISourceable;
54 fd7ee7b1 ben.clark
import eu.etaxonomy.cdm.model.common.Language;
55
import eu.etaxonomy.cdm.model.common.LanguageString;
56
import eu.etaxonomy.cdm.model.common.MultilanguageText;
57 fad74844 Andreas Müller
import eu.etaxonomy.cdm.model.common.OriginalSourceType;
58 fd7ee7b1 ben.clark
import eu.etaxonomy.cdm.model.common.TermVocabulary;
59 c9c6b8e2 Andreas Müller
import eu.etaxonomy.cdm.model.common.TimePeriod;
60 fd7ee7b1 ben.clark
import eu.etaxonomy.cdm.model.media.Media;
61
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
62 812a2ecb Andreas Müller
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
63 1d36aa54 Andreas Müller
import eu.etaxonomy.cdm.model.reference.Reference;
64 22a09e94 Andreas Kohlbecker
import eu.etaxonomy.cdm.model.taxon.Taxon;
65 57606ee3 Andreas Müller
import eu.etaxonomy.cdm.strategy.merge.Merge;
66
import eu.etaxonomy.cdm.strategy.merge.MergeMode;
67 fd7ee7b1 ben.clark
68 9479da48 Andreas Müller
/**
69 b22e4839 m.geoffroy
 * The upmost (abstract) class for a piece of information) about
70
 * a {@link SpecimenOrObservationBase specimen}, a {@link Taxon taxon} or even a {@link TaxonNameBase taxon name}.
71
 * A concrete description element assigns descriptive data to one {@link Feature feature}.<BR>
72
 * Experts use the word feature for the property itself but not for the actual
73
 * description element. Therefore naming this class FeatureBase would have
74 22a09e94 Andreas Kohlbecker
 * leaded to confusion.
75 b22e4839 m.geoffroy
 * <P>
76
 * This class corresponds to: <ul>
77
 * <li> DescriptionsBaseType according to the the SDD schema
78
 * <li> InfoItem according to the TDWG ontology
79 4daf2f37 m.geoffroy
 * <li> MeasurementOrFactAtomised according to the ABCD schema
80 b22e4839 m.geoffroy
 * </ul>
81 22a09e94 Andreas Kohlbecker
 *
82 9479da48 Andreas Müller
 * @author m.doering
83
 * @created 08-Nov-2007 13:06:24
84
 */
85 0ae18eec a.babadshanjan
@XmlAccessorType(XmlAccessType.FIELD)
86
@XmlType(name = "DescriptionElementBase", propOrder = {
87 ba08dfd7 Andreas Müller
    "feature",
88
    "inDescription",
89
    "timeperiod",
90
    "modifiers",
91
    "modifyingText",
92
    "media",
93
    "sources"
94 0ae18eec a.babadshanjan
})
95 9479da48 Andreas Müller
@Entity
96 ee91bcd9 ben.clark
@Audited
97 9479da48 Andreas Müller
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
98 9ec690dd Katja Luther
public abstract class DescriptionElementBase extends AnnotatableEntity implements ISourceable<DescriptionElementSource>, IModifiable, IMultiLanguageTextHolder{
99 22a09e94 Andreas Kohlbecker
    private static final long serialVersionUID = 5000910777835755905L;
100
    @SuppressWarnings("unused")
101
    private static final Logger logger = Logger.getLogger(DescriptionElementBase.class);
102
103
    //type, category of information. In structured descriptions characters
104
    @XmlElement(name = "Feature")
105 6cce5702 a.babadshanjan
    @XmlIDREF
106
    @XmlSchemaType(name = "IDREF")
107 ee91bcd9 ben.clark
    @ManyToOne(fetch = FetchType.LAZY)
108 8b74112c Andreas Müller
//    @Cascade(CascadeType.MERGE)   remove cascade #5755
109 d39a3e9e Andreas Kohlbecker
    @IndexedEmbedded // no depth for terms
110 22a09e94 Andreas Kohlbecker
    private Feature feature;
111
112
    @XmlElementWrapper(name = "Modifiers")
113
    @XmlElement(name = "Modifier")
114
    @XmlIDREF
115 ee91bcd9 ben.clark
    @XmlSchemaType(name = "IDREF")
116 22a09e94 Andreas Kohlbecker
    @ManyToMany(fetch = FetchType.LAZY)
117 ee91bcd9 ben.clark
    @JoinTable(name="DescriptionElementBase_Modifier")
118 d39a3e9e Andreas Kohlbecker
    @IndexedEmbedded(depth=1)
119 533cbb43 Andreas Müller
    private Set<DefinedTerm> modifiers = new HashSet<DefinedTerm>();
120 22a09e94 Andreas Kohlbecker
121
    @XmlElement(name = "ModifyingText")
122 d26c2ef9 a.babadshanjan
    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
123 ee91bcd9 ben.clark
    @OneToMany(fetch = FetchType.LAZY)
124
    @JoinTable(name = "DescriptionElementBase_ModifyingText")
125 a13c5f66 Andreas Müller
    @MapKeyJoinColumn(name="modifyingtext_mapkey_id")
126 a21a761d Katja Luther
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
127 d24ca581 Andreas Kohlbecker
    @IndexedEmbedded
128 22a09e94 Andreas Kohlbecker
    private Map<Language,LanguageString> modifyingText = new HashMap<Language,LanguageString>();
129
130
    @XmlElementWrapper(name = "Media")
131
    @XmlElement(name = "Medium")
132 4393fcb0 a.babadshanjan
    @XmlIDREF
133
    @XmlSchemaType(name = "IDREF")
134 ee91bcd9 ben.clark
    @ManyToMany(fetch = FetchType.LAZY)
135 3dd6c00e Andreas Müller
    @OrderColumn(name="sortIndex")
136
    @ListIndexBase(value=0)  //not really needed as this is the default
137 22a09e94 Andreas Kohlbecker
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
138
    private List<Media> media = new ArrayList<Media>();
139
140
    @XmlElement(name = "InDescription")
141
    @XmlIDREF
142 ce025e29 ben.clark
    @XmlSchemaType(name = "IDREF")
143 ee91bcd9 ben.clark
    @ManyToOne(fetch = FetchType.LAZY)
144 903cecc9 Cherian Mathew
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
145 2a5361d0 Andreas Kohlbecker
    @IndexedEmbedded(includeEmbeddedObjectId=true)
146 3dd6c00e Andreas Müller
    private DescriptionBase<?> inDescription;
147 e9829ef9 Andreas Müller
148 c9c6b8e2 Andreas Müller
	@XmlElement(name = "TimePeriod")
149 0a345e59 Andreas Müller
    private TimePeriod timeperiod = TimePeriod.NewInstance();
150 22a09e94 Andreas Kohlbecker
151 57606ee3 Andreas Müller
    @XmlElementWrapper(name = "Sources")
152 ece46ca8 Andreas Kohlbecker
    @XmlElement(name = "DescriptionElementSource")
153 95d79c4d Andreas Müller
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
154 6aa0af63 Katja Luther
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
155 22a09e94 Andreas Kohlbecker
    @Merge(MergeMode.ADD_CLONE)
156
    private Set<DescriptionElementSource> sources = new HashSet<DescriptionElementSource>();
157
158
159
160
    // ************* CONSTRUCTORS *************/
161
    /**
162
     * Class constructor: creates a new empty description element instance.
163
     *
164
     * @see #DescriptionElementBase(Feature)
165
     */
166
    protected DescriptionElementBase(){
167
    }
168
169
    /**
170
     * Class constructor: creates a new description element instance with the
171
     * given {@link Feature feature} that is described or measured.
172
     *
173
     * @param	feature	the feature described or measured
174
     * @see 			#DescriptionElementBase()
175
     */
176
    protected DescriptionElementBase(Feature feature){
177
        if (feature == null){
178
            feature = Feature.UNKNOWN();
179
        }
180
        this.feature = feature;
181
    }
182
183 0ecfd682 Andreas Müller
// ******************** GETTER / SETTER ***********************************/
184
185 22a09e94 Andreas Kohlbecker
    /**
186
     * Returns the list of {@link Media media} (that is pictures, movies,
187
     * recorded sounds ...) <i>this</i> description element is based on.
188
     */
189
    public List<Media> getMedia(){
190
        return this.media;
191
    }
192
193
    /**
194
     * Adds a {@link Media media} to the list of {@link #getMedia() media}
195
     * <i>this</i> description element is based on.
196
     *
197
     * @param media	the media to be added to <i>this</i> description element
198
     * @see    	   	#getMedia()
199
     */
200
    public void addMedia(Media media){
201
        this.media.add(media);
202
    }
203
    /**
204
     * Removes one element from the list of {@link #getMedia() media}
205
     * <i>this</i> description element is based on.
206
     *
207
     * @param  media	the media which should be removed
208
     * @see     		#getMedia()
209
     * @see     		#addMedia(Media)
210
     */
211
    public void removeMedia(Media media){
212
        this.media.remove(media);
213
    }
214
215
    /**
216
     * Returns the {@link DescriptionBase description} that <i>this</i> DescriptionElement is
217
     * part of.
218
     * @return
219
     */
220
    public DescriptionBase getInDescription() {
221
        return this.inDescription;
222
    }
223
224
    /**
225
     * @see	#setInDescription()
226
     */
227
    protected void setInDescription(DescriptionBase inDescription) {
228
        this.inDescription = inDescription;
229
    }
230
231
    /**
232
     * Returns the {@link Feature feature} <i>this</i> description element is for.
233
     * A feature is a property that can be described or measured but not the
234
     * description or the measurement itself.
235
     */
236
    public Feature getFeature(){
237
        return this.feature;
238
    }
239
240
    /**
241
     * @see	#getFeature()
242
     */
243
    public void setFeature(Feature feature){
244
        this.feature = feature;
245
    }
246
247
    /**
248 e9829ef9 Andreas Müller
	 * The point in time, the time period or the season for which this description element
249
	 * is valid. A season may be expressed by not filling the year part(s) of the time period.
250 c9c6b8e2 Andreas Müller
	 */
251
	public TimePeriod getTimeperiod() {
252
		return timeperiod;
253
	}
254
255
	/**
256
	 * @see #getTimeperiod()
257
	 */
258
	public void setTimeperiod(TimePeriod timeperiod) {
259
		if (timeperiod == null){
260
			timeperiod = TimePeriod.NewInstance();
261
		}
262
		this.timeperiod = timeperiod;
263
	}
264
265
	/**
266 22a09e94 Andreas Kohlbecker
     * Returns the set of {@link Modifier modifiers} used to qualify the validity of
267
     * <i>this</i> description element. This is only metainformation.
268
     */
269 e9829ef9 Andreas Müller
    @Override
270 533cbb43 Andreas Müller
    public Set<DefinedTerm> getModifiers(){
271 22a09e94 Andreas Kohlbecker
        return this.modifiers;
272
    }
273
274
    /**
275
     * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}
276
     * used to qualify the validity of <i>this</i> description element.
277
     *
278
     * @param modifier	the modifier to be added to <i>this</i> description element
279
     * @see    	   		#getModifiers()
280
     */
281 e9829ef9 Andreas Müller
    @Override
282 533cbb43 Andreas Müller
    public void addModifier(DefinedTerm modifier){
283 22a09e94 Andreas Kohlbecker
        this.modifiers.add(modifier);
284
    }
285
    /**
286
     * Removes one element from the set of {@link #getModifiers() modifiers}
287
     * used to qualify the validity of <i>this</i> description element.
288
     *
289
     * @param  modifier	the modifier which should be removed
290
     * @see     		#getModifiers()
291
     * @see     		#addModifier(Modifier)
292
     */
293 e9829ef9 Andreas Müller
    @Override
294 533cbb43 Andreas Müller
    public void removeModifier(DefinedTerm modifier){
295 22a09e94 Andreas Kohlbecker
        this.modifiers.remove(modifier);
296
    }
297
298
299
    /**
300
     * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity
301
     * of <i>this</i> description element.  The different {@link LanguageString language strings}
302
     * contained in the multilanguage text should all have the same meaning.<BR>
303
     * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}
304
     * as a {@link Modifier modifier} does.
305
     * <P>
306
     * NOTE: the actual content of <i>this</i> description element is NOT
307
     * stored in the modifying text. This is only metainformation
308
     * (like "Some experts express doubt about this assertion").
309
     */
310
    public Map<Language,LanguageString> getModifyingText(){
311
        return this.modifyingText;
312
    }
313
314
    /**
315
     * Adds a translated {@link LanguageString text in a particular language}
316
     * to the {@link MultilanguageText multilanguage text} used to qualify the validity
317
     * of <i>this</i> description element.
318
     *
319
     * @param description	the language string describing the validity
320
     * 						in a particular language
321
     * @see    	   			#getModifyingText()
322
     * @see    	   			#putModifyingText(Language, String)
323
     * @deprecated 			should follow the put semantic of maps, this method will be removed in v4.0
324
     * 						Use the {@link #putModifyingText(LanguageString) putModifyingText} method
325
     */
326 e9829ef9 Andreas Müller
    @Deprecated
327 22a09e94 Andreas Kohlbecker
    public LanguageString addModifyingText(LanguageString description){
328
        return this.putModifyingText(description);
329
    }
330
331
    /**
332
     * Adds a translated {@link LanguageString text in a particular language}
333
     * to the {@link MultilanguageText multilanguage text} used to qualify the validity
334
     * of <i>this</i> description element.
335
     *
336
     * @param description	the language string describing the validity
337
     * 						in a particular language
338
     * @see    	   			#getModifyingText()
339
     * @see    	   			#putModifyingText(Language, String)
340
     */
341
    public LanguageString putModifyingText(LanguageString description){
342
        return this.modifyingText.put(description.getLanguage(),description);
343
    }
344
    /**
345
     * Creates a {@link LanguageString language string} based on the given text string
346
     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
347
     * used to qualify the validity of <i>this</i> description element.
348
     *
349
     * @param text		the string describing the validity
350
     * 					in a particular language
351
     * @param language	the language in which the text string is formulated
352
     * @see    	   		#getModifyingText()
353
     * @see    	   		#putModifyingText(LanguageString)
354
     * @deprecated 		should follow the put semantic of maps, this method will be removed in v4.0
355
     * 					Use the {@link #putModifyingText(Language, String) putModifyingText} method
356
     */
357 e9829ef9 Andreas Müller
    @Deprecated
358 22a09e94 Andreas Kohlbecker
    public LanguageString addModifyingText(String text, Language language){
359
        return this.putModifyingText(language, text);
360
    }
361
362
    /**
363
     * Creates a {@link LanguageString language string} based on the given text string
364
     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
365
     * used to qualify the validity of <i>this</i> description element.
366
     *
367
     * @param language	the language in which the text string is formulated
368
     * @param text		the string describing the validity
369
     * 					in a particular language
370
     *
371
     * @see    	   		#getModifyingText()
372
     * @see    	   		#putModifyingText(LanguageString)
373
     *
374
     */
375
    public LanguageString putModifyingText(Language language, String text){
376
        return this.modifyingText.put(language, LanguageString.NewInstance(text, language));
377
    }
378
    /**
379
     * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity
380
     * of <i>this</i> description element the one {@link LanguageString language string}
381
     * with the given {@link Language language}.
382
     *
383
     * @param  language	the language in which the language string to be removed
384
     * 					has been formulated
385
     * @see     		#getModifyingText()
386
     */
387
    public LanguageString removeModifyingText(Language language){
388
        return this.modifyingText.remove(language);
389
    }
390
391
    /* (non-Javadoc)
392
     * @see eu.etaxonomy.cdm.model.common.ISourceable#getSources()
393
     */
394 e9829ef9 Andreas Müller
    @Override
395 22a09e94 Andreas Kohlbecker
    public Set<DescriptionElementSource> getSources() {
396
        return this.sources;
397
    }
398
399 e9829ef9 Andreas Müller
    @Override
400 22a09e94 Andreas Kohlbecker
    public void addSource(DescriptionElementSource source) {
401
        if (source != null){
402
            this.sources.add(source);
403
        }
404
    }
405
406 e9829ef9 Andreas Müller
    @Override
407 fad74844 Andreas Müller
    public DescriptionElementSource addSource(OriginalSourceType type, String id, String idNamespace, Reference citation, String microCitation) {
408 22a09e94 Andreas Kohlbecker
        if (id == null && idNamespace == null && citation == null && microCitation == null){
409
            return null;
410
        }
411 fad74844 Andreas Müller
        DescriptionElementSource source = DescriptionElementSource.NewInstance(type, id, idNamespace, citation, microCitation);
412
        addSource(source);
413
        return source;
414
    }
415 c52b7e11 Katja Luther
    @Override
416
    public void addSources(Set<DescriptionElementSource> sources){
417
    	for (DescriptionElementSource source:sources){
418
    		addSource(source);
419
    	}
420
    }
421 e9829ef9 Andreas Müller
422 fad74844 Andreas Müller
    @Override
423 90046bc4 Andreas Müller
    public DescriptionElementSource addImportSource(String id, String idNamespace, Reference citation, String microCitation) {
424 fad74844 Andreas Müller
        if (id == null && idNamespace == null && citation == null && microCitation == null){
425
            return null;
426
        }
427
        DescriptionElementSource source = DescriptionElementSource.NewInstance(OriginalSourceType.Import, id, idNamespace, citation, microCitation);
428 22a09e94 Andreas Kohlbecker
        addSource(source);
429
        return source;
430
    }
431
432 fad74844 Andreas Müller
    /**
433
     * Adds a {@link IOriginalSource source} to this description element.
434
     * @param type the type of the source
435 e9829ef9 Andreas Müller
     * @param idInSource the id used in the source
436 fad74844 Andreas Müller
     * @param idNamespace the namespace for the id in the source
437
     * @param citation the source as a {@link Reference reference}
438
     * @param microReference the details (e.g. page number) in the reference
439
     * @param nameUsedInSource the taxon name used in the source
440
     * @param originalNameString the name as text used in the source
441
     */
442
    public void addSource(OriginalSourceType type, String idInSource, String idNamespace, Reference citation, String microReference, TaxonNameBase nameUsedInSource, String originalNameString){
443
        DescriptionElementSource newSource = DescriptionElementSource.NewInstance(type, idInSource, idNamespace, citation, microReference, nameUsedInSource, originalNameString);
444 22a09e94 Andreas Kohlbecker
        addSource(newSource);
445
    }
446
447 e9829ef9 Andreas Müller
    @Override
448 22a09e94 Andreas Kohlbecker
    public void removeSource(DescriptionElementSource source) {
449
        this.sources.remove(source);
450
    }
451
452
// ******************* METHODS *************************************************************/
453
454 533cbb43 Andreas Müller
    protected Map<TermVocabulary, List<DefinedTerm>> makeModifierMap(){
455
        Map<TermVocabulary, List<DefinedTerm>> result = new HashMap<TermVocabulary, List<DefinedTerm>>();
456
        for (DefinedTerm modifier : getModifiers()){
457
            TermVocabulary<DefinedTerm> voc = modifier.getVocabulary();
458 22a09e94 Andreas Kohlbecker
            if (result.get(voc) == null){
459 533cbb43 Andreas Müller
                result.put(voc, new ArrayList<DefinedTerm>());
460 22a09e94 Andreas Kohlbecker
            }
461
            result.get(voc).add(modifier);
462
        }
463
        return result;
464
    }
465
466 533cbb43 Andreas Müller
    public List<DefinedTerm> getModifiers(TermVocabulary voc){
467
        List<DefinedTerm> result = makeModifierMap().get(voc);
468 22a09e94 Andreas Kohlbecker
        if (result == null){
469 533cbb43 Andreas Müller
            result = new ArrayList<DefinedTerm>();
470 22a09e94 Andreas Kohlbecker
        }
471
        return result;
472
    }
473
474
475
476
//************************** CLONE **********************************************************/
477
478
    /**
479
     * Clones the description element. The element is <b>not</b> added to the same
480
     * description as the orginal element (inDescription is set to <code>null</null>).
481
     * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
482
     */
483
    @Override
484
    public Object clone() throws CloneNotSupportedException{
485
        DescriptionElementBase result = (DescriptionElementBase)super.clone();
486
487
        //inDescription
488
        result.inDescription = null;
489
490
        //Sources
491
        result.sources = new HashSet<DescriptionElementSource>();
492
        for (DescriptionElementSource source : getSources()){
493
            DescriptionElementSource newSource = (DescriptionElementSource)source.clone();
494
            result.addSource(newSource);
495
        }
496
497
        //media
498
        result.media = new ArrayList<Media>();
499
        for (Media media : getMedia()){
500
            result.media.add(media);
501
        }
502
503
        //modifying text
504
        result.modifyingText = new HashMap<Language, LanguageString>();
505
        for (Language language : getModifyingText().keySet()){
506
            //TODO clone needed? See also IndividualsAssociation
507
            LanguageString newLanguageString = (LanguageString)getModifyingText().get(language).clone();
508
            result.modifyingText.put(language, newLanguageString);
509
        }
510
511
        //modifiers
512 533cbb43 Andreas Müller
        result.modifiers = new HashSet<DefinedTerm>();
513
        for (DefinedTerm modifier : getModifiers()){
514 22a09e94 Andreas Kohlbecker
            result.modifiers.add(modifier);
515
        }
516
517
        //no changes to: feature
518
        return result;
519
    }
520
521
    /**
522
     * Clones the description element.<BR>
523
     * The new element is added to the <code>description</code>.<BR>
524
     * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
525
     */
526
    public DescriptionElementBase clone(DescriptionBase description) throws CloneNotSupportedException{
527
        DescriptionElementBase result = (DescriptionElementBase)clone();
528
        description.addElement(result);
529
        return result;
530
    }
531
532 e9829ef9 Andreas Müller
    /**
533
     * Is this description item of a class type which is considere to
534
     * represent character data? These classes are {@link QuantitativeData}
535
     * and {@link CategoricalData}.
536
     * To be overriden by these classes.
537
     */
538
    @Transient
539
    @XmlTransient
540
    public boolean isCharacterData() {
541
        return false;
542
    }
543
544 22a09e94 Andreas Kohlbecker
545 9479da48 Andreas Müller
}