2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.description
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
20 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 import javax
.persistence
.OneToMany
;
28 import javax
.persistence
.Transient
;
29 import javax
.xml
.bind
.annotation
.XmlAccessType
;
30 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
31 import javax
.xml
.bind
.annotation
.XmlElement
;
32 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
33 import javax
.xml
.bind
.annotation
.XmlIDREF
;
34 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
35 import javax
.xml
.bind
.annotation
.XmlType
;
36 import javax
.xml
.bind
.annotation
.adapters
.XmlJavaTypeAdapter
;
38 import org
.apache
.log4j
.Logger
;
39 import org
.hibernate
.annotations
.Cascade
;
40 import org
.hibernate
.annotations
.CascadeType
;
41 import org
.hibernate
.annotations
.IndexColumn
;
42 import org
.hibernate
.envers
.Audited
;
43 import org
.hibernate
.search
.annotations
.IndexedEmbedded
;
45 import eu
.etaxonomy
.cdm
.jaxb
.MultilanguageTextAdapter
;
46 import eu
.etaxonomy
.cdm
.model
.common
.DescriptionElementSource
;
47 import eu
.etaxonomy
.cdm
.model
.common
.ISourceable
;
48 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
49 import eu
.etaxonomy
.cdm
.model
.common
.LanguageString
;
50 import eu
.etaxonomy
.cdm
.model
.common
.MultilanguageText
;
51 import eu
.etaxonomy
.cdm
.model
.common
.ReferencedEntityBase
;
52 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
53 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
54 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
55 import eu
.etaxonomy
.cdm
.model
.occurrence
.SpecimenOrObservationBase
;
56 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
57 import eu
.etaxonomy
.cdm
.strategy
.merge
.Merge
;
58 import eu
.etaxonomy
.cdm
.strategy
.merge
.MergeMode
;
61 * The upmost (abstract) class for a piece of information) about
62 * a {@link SpecimenOrObservationBase specimen}, a {@link Taxon taxon} or even a {@link TaxonNameBase taxon name}.
63 * A concrete description element assigns descriptive data to one {@link Feature feature}.<BR>
64 * Experts use the word feature for the property itself but not for the actual
65 * description element. Therefore naming this class FeatureBase would have
66 * leaded to confusion.
68 * This class corresponds to: <ul>
69 * <li> DescriptionsBaseType according to the the SDD schema
70 * <li> InfoItem according to the TDWG ontology
71 * <li> MeasurementOrFactAtomised according to the ABCD schema
76 * @created 08-Nov-2007 13:06:24
78 @XmlAccessorType(XmlAccessType
.FIELD
)
79 @XmlType(name
= "DescriptionElementBase", propOrder
= {
85 "nameUsedInReference",
90 @Inheritance(strategy
=InheritanceType
.SINGLE_TABLE
)
91 public abstract class DescriptionElementBase
extends ReferencedEntityBase
implements ISourceable
<DescriptionElementSource
> {
92 private static final long serialVersionUID
= 5000910777835755905L;
93 @SuppressWarnings("unused")
94 private static final Logger logger
= Logger
.getLogger(DescriptionElementBase
.class);
96 //type, category of information. In structured descriptions characters
97 @XmlElement(name
= "Feature")
99 @XmlSchemaType(name
= "IDREF")
100 @ManyToOne(fetch
= FetchType
.LAZY
)
102 private Feature feature
;
104 @XmlElementWrapper(name
= "Modifiers")
105 @XmlElement(name
= "Modifier")
107 @XmlSchemaType(name
= "IDREF")
108 @ManyToMany(fetch
= FetchType
.LAZY
)
109 @JoinTable(name
="DescriptionElementBase_Modifier")
110 private Set
<Modifier
> modifiers
= new HashSet
<Modifier
>();
112 @XmlElement(name
= "ModifyingText")
113 @XmlJavaTypeAdapter(MultilanguageTextAdapter
.class)
114 @OneToMany(fetch
= FetchType
.LAZY
)
115 @JoinTable(name
= "DescriptionElementBase_ModifyingText")
116 private Map
<Language
,LanguageString
> modifyingText
= new HashMap
<Language
,LanguageString
>();
118 @XmlElementWrapper(name
= "Media")
119 @XmlElement(name
= "Medium")
121 @XmlSchemaType(name
= "IDREF")
122 @ManyToMany(fetch
= FetchType
.LAZY
)
123 @IndexColumn(name
="sortIndex", base
= 0)
124 @Cascade({CascadeType
.SAVE_UPDATE
})
125 private List
<Media
> media
= new ArrayList
<Media
>();
127 @XmlElement(name
= "InDescription")
129 @XmlSchemaType(name
= "IDREF")
130 @ManyToOne(fetch
= FetchType
.LAZY
)
131 @Cascade(CascadeType
.SAVE_UPDATE
)
133 private DescriptionBase inDescription
;
135 //TODO can this be handled together with ReferencedEntityBase.originalNameString??
136 @XmlElement(name
= "nameUsedInReference")
138 @XmlSchemaType(name
= "IDREF")
139 @ManyToOne(fetch
= FetchType
.LAZY
)
140 @Cascade({CascadeType
.SAVE_UPDATE
})
141 private TaxonNameBase nameUsedInReference
;
143 @XmlElementWrapper(name
= "Sources")
144 @XmlElement(name
= "OriginalSource")
145 @OneToMany(fetch
= FetchType
.LAZY
)
146 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
147 @Merge(MergeMode
.ADD_CLONE
)
148 private Set
<DescriptionElementSource
> sources
= new HashSet
<DescriptionElementSource
>();
152 // ************* CONSTRUCTORS *************/
154 * Class constructor: creates a new empty description element instance.
156 * @see #DescriptionElementBase(Feature)
158 protected DescriptionElementBase(){
162 * Class constructor: creates a new description element instance with the
163 * given {@link Feature feature} that is described or measured.
165 * @param feature the feature described or measured
166 * @see #DescriptionElementBase()
168 protected DescriptionElementBase(Feature feature
){
169 if (feature
== null){
170 feature
= Feature
.UNKNOWN();
172 this.feature
= feature
;
176 * Returns the set of {@link Media media} (that is pictures, movies,
177 * recorded sounds ...) <i>this</i> description element is based on.
179 public List
<Media
> getMedia(){
184 * Adds a {@link Media media} to the set of {@link #getMedia() media}
185 * <i>this</i> description element is based on.
187 * @param media the media to be added to <i>this</i> description element
190 public void addMedia(Media media
){
191 this.media
.add(media
);
194 * Removes one element from the set of {@link #getMedia() media}
195 * <i>this</i> description element is based on.
197 * @param media the media which should be removed
199 * @see #addMedia(Media)
201 public void removeMedia(Media media
){
202 this.media
.remove(media
);
206 * Returns the {@link DescriptionBase description} that <i>this</i> DescriptionElement is
210 public DescriptionBase
getInDescription() {
211 return this.inDescription
;
215 * @see #setInDescription()
217 protected void setInDescription(DescriptionBase inDescription
) {
218 this.inDescription
= inDescription
;
222 * Does exactly the same as getFeature().
224 * FIXME Is there a need to have two methods with different names which do the same thing?
229 public Feature
getType(){
230 return this.getFeature();
233 * Does exactly the same as setFeature(Feature).
235 * @param type the feature to be described or measured
236 * @see #setFeature(Feature)
239 public void setType(Feature type
){
240 this.setFeature(type
);
244 * Returns the {@link Feature feature} <i>this</i> description element is for.
245 * A feature is a property that can be described or measured but not the
246 * description or the measurement itself.
248 public Feature
getFeature(){
255 public void setFeature(Feature feature
){
256 this.feature
= feature
;
260 * Returns the set of {@link Modifier modifiers} used to qualify the validity of
261 * <i>this</i> description element. This is only metainformation.
263 public Set
<Modifier
> getModifiers(){
264 return this.modifiers
;
268 * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}
269 * used to qualify the validity of <i>this</i> description element.
271 * @param modifier the modifier to be added to <i>this</i> description element
272 * @see #getModifiers()
274 public void addModifier(Modifier modifier
){
275 this.modifiers
.add(modifier
);
278 * Removes one element from the set of {@link #getModifiers() modifiers}
279 * used to qualify the validity of <i>this</i> description element.
281 * @param modifier the modifier which should be removed
282 * @see #getModifiers()
283 * @see #addModifier(Modifier)
285 public void removeModifier(Modifier modifier
){
286 this.modifiers
.remove(modifier
);
291 * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity
292 * of <i>this</i> description element. The different {@link LanguageString language strings}
293 * contained in the multilanguage text should all have the same meaning.<BR>
294 * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}
295 * as a {@link Modifier modifier} does.
297 * NOTE: the actual content of <i>this</i> description element is NOT
298 * stored in the modifying text. This is only metainformation
299 * (like "Some experts express doubt about this assertion").
301 public Map
<Language
,LanguageString
> getModifyingText(){
302 return this.modifyingText
;
306 * Adds a translated {@link LanguageString text in a particular language}
307 * to the {@link MultilanguageText multilanguage text} used to qualify the validity
308 * of <i>this</i> description element.
310 * @param description the language string describing the validity
311 * in a particular language
312 * @see #getModifyingText()
313 * @see #addModifyingText(String, Language)
315 public LanguageString
addModifyingText(LanguageString description
){
316 return this.modifyingText
.put(description
.getLanguage(),description
);
319 * Creates a {@link LanguageString language string} based on the given text string
320 * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
321 * used to qualify the validity of <i>this</i> description element.
323 * @param text the string describing the validity
324 * in a particular language
325 * @param language the language in which the text string is formulated
326 * @see #getModifyingText()
327 * @see #addModifyingText(LanguageString)
329 public LanguageString
addModifyingText(String text
, Language language
){
330 return this.modifyingText
.put(language
, LanguageString
.NewInstance(text
, language
));
333 * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity
334 * of <i>this</i> description element the one {@link LanguageString language string}
335 * with the given {@link Language language}.
337 * @param language the language in which the language string to be removed
338 * has been formulated
339 * @see #getModifyingText()
341 public LanguageString
removeModifyingText(Language language
){
342 return this.modifyingText
.remove(language
);
346 * @see eu.etaxonomy.cdm.model.common.ISourceable#getSources()
348 public Set
<DescriptionElementSource
> getSources() {
353 * @see eu.etaxonomy.cdm.model.common.ISourceable#addSource(eu.etaxonomy.cdm.model.common.IOriginalSource)
355 public void addSource(DescriptionElementSource source
) {
357 DescriptionElementBase oldSourcedObj
= source
.getSourcedObj();
358 if (oldSourcedObj
!= null && oldSourcedObj
!= this){
359 oldSourcedObj
.getSources().remove(source
);
361 this.sources
.add(source
);
362 source
.setSourcedObj(this);
367 * @see eu.etaxonomy.cdm.model.common.ISourceable#removeSource(eu.etaxonomy.cdm.model.common.IOriginalSource)
369 public void removeSource(DescriptionElementSource source
) {
370 this.sources
.remove(source
);
375 * @return the nameUsedInReference
377 public TaxonNameBase
getNameUsedInReference() {
378 return nameUsedInReference
;
382 * @param nameUsedInReference the nameUsedInReference to set
384 public void setNameUsedInReference(TaxonNameBase nameUsedInReference
) {
385 this.nameUsedInReference
= nameUsedInReference
;