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

Revision 13569, 17.7 kB (checked in by a.kohlbecker, 5 months ago)

lucene search: multi instance configuration fixed, native lucene search, ....

  • 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
12
13import java.util.ArrayList;
14import java.util.HashMap;
15import java.util.HashSet;
16import java.util.List;
17import java.util.Map;
18import java.util.Set;
19
20import javax.persistence.Entity;
21import javax.persistence.FetchType;
22import javax.persistence.Inheritance;
23import javax.persistence.InheritanceType;
24import javax.persistence.JoinTable;
25import javax.persistence.ManyToMany;
26import javax.persistence.ManyToOne;
27import javax.persistence.OneToMany;
28import javax.xml.bind.annotation.XmlAccessType;
29import javax.xml.bind.annotation.XmlAccessorType;
30import javax.xml.bind.annotation.XmlElement;
31import javax.xml.bind.annotation.XmlElementWrapper;
32import javax.xml.bind.annotation.XmlIDREF;
33import javax.xml.bind.annotation.XmlSchemaType;
34import javax.xml.bind.annotation.XmlType;
35import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
36
37import org.apache.log4j.Logger;
38import org.hibernate.annotations.Cascade;
39import org.hibernate.annotations.CascadeType;
40import org.hibernate.annotations.IndexColumn;
41import org.hibernate.envers.Audited;
42import org.hibernate.search.annotations.IndexedEmbedded;
43
44import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
45import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
46import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
47import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
48import eu.etaxonomy.cdm.model.common.ISourceable;
49import eu.etaxonomy.cdm.model.common.Language;
50import eu.etaxonomy.cdm.model.common.LanguageString;
51import eu.etaxonomy.cdm.model.common.MultilanguageText;
52import eu.etaxonomy.cdm.model.common.TermVocabulary;
53import eu.etaxonomy.cdm.model.media.Media;
54import eu.etaxonomy.cdm.model.name.TaxonNameBase;
55import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
56import eu.etaxonomy.cdm.model.reference.Reference;
57import eu.etaxonomy.cdm.model.taxon.Taxon;
58import eu.etaxonomy.cdm.strategy.merge.Merge;
59import eu.etaxonomy.cdm.strategy.merge.MergeMode;
60
61/**
62 * The upmost (abstract) class for a piece of information) about
63 * a {@link SpecimenOrObservationBase specimen}, a {@link Taxon taxon} or even a {@link TaxonNameBase taxon name}.
64 * A concrete description element assigns descriptive data to one {@link Feature feature}.<BR>
65 * Experts use the word feature for the property itself but not for the actual
66 * description element. Therefore naming this class FeatureBase would have
67 * leaded to confusion.
68 * <P>
69 * This class corresponds to: <ul>
70 * <li> DescriptionsBaseType according to the the SDD schema
71 * <li> InfoItem according to the TDWG ontology
72 * <li> MeasurementOrFactAtomised according to the ABCD schema
73 * </ul>
74 *
75 * @author m.doering
76 * @version 1.0
77 * @created 08-Nov-2007 13:06:24
78 */
79@XmlAccessorType(XmlAccessType.FIELD)
80@XmlType(name = "DescriptionElementBase", propOrder = {
81        "feature",
82        "modifiers",
83        "modifyingText",
84        "media",
85        "inDescription",
86        "sources"
87})
88@Entity
89@Audited
90@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
91public abstract class DescriptionElementBase extends AnnotatableEntity implements ISourceable<DescriptionElementSource>, IModifiable, IMultiLanguageTextHolder{
92    private static final long serialVersionUID = 5000910777835755905L;
93    @SuppressWarnings("unused")
94    private static final Logger logger = Logger.getLogger(DescriptionElementBase.class);
95
96    //type, category of information. In structured descriptions characters
97    @XmlElement(name = "Feature")
98    @XmlIDREF
99    @XmlSchemaType(name = "IDREF")
100    @ManyToOne(fetch = FetchType.LAZY)
101    //@Cascade(CascadeType.SAVE_UPDATE)
102    @Cascade(CascadeType.MERGE)
103    @IndexedEmbedded
104    private Feature feature;
105
106    @XmlElementWrapper(name = "Modifiers")
107    @XmlElement(name = "Modifier")
108    @XmlIDREF
109    @XmlSchemaType(name = "IDREF")
110    @ManyToMany(fetch = FetchType.LAZY)
111    @JoinTable(name="DescriptionElementBase_Modifier")
112    private Set<Modifier> modifiers = new HashSet<Modifier>();
113
114    @XmlElement(name = "ModifyingText")
115    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
116    @OneToMany(fetch = FetchType.LAZY)
117    @JoinTable(name = "DescriptionElementBase_ModifyingText")
118    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
119    private Map<Language,LanguageString> modifyingText = new HashMap<Language,LanguageString>();
120
121    @XmlElementWrapper(name = "Media")
122    @XmlElement(name = "Medium")
123    @XmlIDREF
124    @XmlSchemaType(name = "IDREF")
125    @ManyToMany(fetch = FetchType.LAZY)
126    @IndexColumn(name="sortIndex", base = 0)
127    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
128    private List<Media> media = new ArrayList<Media>();
129
130    @XmlElement(name = "InDescription")
131    @XmlIDREF
132    @XmlSchemaType(name = "IDREF")
133    @ManyToOne(fetch = FetchType.LAZY)
134    @Cascade(CascadeType.SAVE_UPDATE)
135    @IndexedEmbedded
136    private DescriptionBase inDescription;
137
138    @XmlElementWrapper(name = "Sources")
139    @XmlElement(name = "DescriptionElementSource")
140    @OneToMany(fetch = FetchType.LAZY)
141    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN})
142    @Merge(MergeMode.ADD_CLONE)
143    private Set<DescriptionElementSource> sources = new HashSet<DescriptionElementSource>();
144
145
146
147    // ************* CONSTRUCTORS *************/
148    /**
149     * Class constructor: creates a new empty description element instance.
150     *
151     * @see #DescriptionElementBase(Feature)
152     */
153    protected DescriptionElementBase(){
154    }
155
156    /**
157     * Class constructor: creates a new description element instance with the
158     * given {@link Feature feature} that is described or measured.
159     *
160     * @param   feature the feature described or measured
161     * @see                     #DescriptionElementBase()
162     */
163    protected DescriptionElementBase(Feature feature){
164        if (feature == null){
165            feature = Feature.UNKNOWN();
166        }
167        this.feature = feature;
168    }
169
170    /**
171     * Returns the list of {@link Media media} (that is pictures, movies,
172     * recorded sounds ...) <i>this</i> description element is based on.
173     */
174    public List<Media> getMedia(){
175        return this.media;
176    }
177
178    /**
179     * Adds a {@link Media media} to the list of {@link #getMedia() media}
180     * <i>this</i> description element is based on.
181     *
182     * @param media     the media to be added to <i>this</i> description element
183     * @see             #getMedia()
184     */
185    public void addMedia(Media media){
186        this.media.add(media);
187    }
188    /**
189     * Removes one element from the list of {@link #getMedia() media}
190     * <i>this</i> description element is based on.
191     *
192     * @param  media    the media which should be removed
193     * @see                     #getMedia()
194     * @see                     #addMedia(Media)
195     */
196    public void removeMedia(Media media){
197        this.media.remove(media);
198    }
199
200    /**
201     * Returns the {@link DescriptionBase description} that <i>this</i> DescriptionElement is
202     * part of.
203     * @return
204     */
205    public DescriptionBase getInDescription() {
206        return this.inDescription;
207    }
208
209    /**
210     * @see     #setInDescription()
211     */
212    protected void setInDescription(DescriptionBase inDescription) {
213        this.inDescription = inDescription;
214    }
215
216    /**
217     * Returns the {@link Feature feature} <i>this</i> description element is for.
218     * A feature is a property that can be described or measured but not the
219     * description or the measurement itself.
220     */
221    public Feature getFeature(){
222        return this.feature;
223    }
224
225    /**
226     * @see     #getFeature()
227     */
228    public void setFeature(Feature feature){
229        this.feature = feature;
230    }
231
232    /**
233     * Returns the set of {@link Modifier modifiers} used to qualify the validity of
234     * <i>this</i> description element. This is only metainformation.
235     */
236    public Set<Modifier> getModifiers(){
237        return this.modifiers;
238    }
239
240    /**
241     * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}
242     * used to qualify the validity of <i>this</i> description element.
243     *
244     * @param modifier  the modifier to be added to <i>this</i> description element
245     * @see                     #getModifiers()
246     */
247    public void addModifier(Modifier modifier){
248        this.modifiers.add(modifier);
249    }
250    /**
251     * Removes one element from the set of {@link #getModifiers() modifiers}
252     * used to qualify the validity of <i>this</i> description element.
253     *
254     * @param  modifier the modifier which should be removed
255     * @see                     #getModifiers()
256     * @see                     #addModifier(Modifier)
257     */
258    public void removeModifier(Modifier modifier){
259        this.modifiers.remove(modifier);
260    }
261
262
263    /**
264     * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity
265     * of <i>this</i> description element.  The different {@link LanguageString language strings}
266     * contained in the multilanguage text should all have the same meaning.<BR>
267     * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}
268     * as a {@link Modifier modifier} does.
269     * <P>
270     * NOTE: the actual content of <i>this</i> description element is NOT
271     * stored in the modifying text. This is only metainformation
272     * (like "Some experts express doubt about this assertion").
273     */
274    public Map<Language,LanguageString> getModifyingText(){
275        return this.modifyingText;
276    }
277
278    /**
279     * Adds a translated {@link LanguageString text in a particular language}
280     * to the {@link MultilanguageText multilanguage text} used to qualify the validity
281     * of <i>this</i> description element.
282     *
283     * @param description       the language string describing the validity
284     *                                          in a particular language
285     * @see                             #getModifyingText()
286     * @see                             #putModifyingText(Language, String)
287     * @deprecated                      should follow the put semantic of maps, this method will be removed in v4.0
288     *                                          Use the {@link #putModifyingText(LanguageString) putModifyingText} method
289     */
290    public LanguageString addModifyingText(LanguageString description){
291        return this.putModifyingText(description);
292    }
293
294    /**
295     * Adds a translated {@link LanguageString text in a particular language}
296     * to the {@link MultilanguageText multilanguage text} used to qualify the validity
297     * of <i>this</i> description element.
298     *
299     * @param description       the language string describing the validity
300     *                                          in a particular language
301     * @see                             #getModifyingText()
302     * @see                             #putModifyingText(Language, String)
303     */
304    public LanguageString putModifyingText(LanguageString description){
305        return this.modifyingText.put(description.getLanguage(),description);
306    }
307    /**
308     * Creates a {@link LanguageString language string} based on the given text string
309     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
310     * used to qualify the validity of <i>this</i> description element.
311     *
312     * @param text              the string describing the validity
313     *                                  in a particular language
314     * @param language  the language in which the text string is formulated
315     * @see                     #getModifyingText()
316     * @see                     #putModifyingText(LanguageString)
317     * @deprecated              should follow the put semantic of maps, this method will be removed in v4.0
318     *                                  Use the {@link #putModifyingText(Language, String) putModifyingText} method
319     */
320    public LanguageString addModifyingText(String text, Language language){
321        return this.putModifyingText(language, text);
322    }
323
324    /**
325     * Creates a {@link LanguageString language string} based on the given text string
326     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
327     * used to qualify the validity of <i>this</i> description element.
328     *
329     * @param language  the language in which the text string is formulated
330     * @param text              the string describing the validity
331     *                                  in a particular language
332     *
333     * @see                     #getModifyingText()
334     * @see                     #putModifyingText(LanguageString)
335     *
336     */
337    public LanguageString putModifyingText(Language language, String text){
338        return this.modifyingText.put(language, LanguageString.NewInstance(text, language));
339    }
340    /**
341     * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity
342     * of <i>this</i> description element the one {@link LanguageString language string}
343     * with the given {@link Language language}.
344     *
345     * @param  language the language in which the language string to be removed
346     *                                  has been formulated
347     * @see                     #getModifyingText()
348     */
349    public LanguageString removeModifyingText(Language language){
350        return this.modifyingText.remove(language);
351    }
352
353    /* (non-Javadoc)
354     * @see eu.etaxonomy.cdm.model.common.ISourceable#getSources()
355     */
356    public Set<DescriptionElementSource> getSources() {
357        return this.sources;
358    }
359
360    /* (non-Javadoc)
361     * @see eu.etaxonomy.cdm.model.common.ISourceable#addSource(eu.etaxonomy.cdm.model.common.IOriginalSource)
362     */
363    public void addSource(DescriptionElementSource source) {
364        if (source != null){
365            DescriptionElementBase oldSourcedObj = source.getSourcedObj();
366            if (oldSourcedObj != null && oldSourcedObj != this){
367                oldSourcedObj.getSources().remove(source);
368            }
369            this.sources.add(source);
370            source.setSourcedObj(this);
371        }
372    }
373
374    /* (non-Javadoc)
375     * @see eu.etaxonomy.cdm.model.common.ISourceable#addSource(java.lang.String, java.lang.String, eu.etaxonomy.cdm.model.reference.Reference, java.lang.String)
376     */
377    public DescriptionElementSource addSource(String id, String idNamespace, Reference citation, String microCitation) {
378        if (id == null && idNamespace == null && citation == null && microCitation == null){
379            return null;
380        }
381        DescriptionElementSource source = DescriptionElementSource.NewInstance(id, idNamespace, citation, microCitation);
382        addSource(source);
383        return source;
384    }
385
386    public void addSource(String id, String idNamespace, Reference citation, String microReference, TaxonNameBase nameUsedInSource, String originalNameString){
387        DescriptionElementSource newSource = DescriptionElementSource.NewInstance(id, idNamespace, citation, microReference, nameUsedInSource, originalNameString);
388        addSource(newSource);
389    }
390
391    /* (non-Javadoc)
392     * @see eu.etaxonomy.cdm.model.common.ISourceable#removeSource(eu.etaxonomy.cdm.model.common.IOriginalSource)
393     */
394    public void removeSource(DescriptionElementSource source) {
395        this.sources.remove(source);
396    }
397
398// ******************* METHODS *************************************************************/
399
400    protected Map<TermVocabulary, List<Modifier>> makeModifierMap(){
401        Map<TermVocabulary, List<Modifier>> result = new HashMap<TermVocabulary, List<Modifier>>();
402        for (Modifier modifier : getModifiers()){
403            TermVocabulary<Modifier> voc = modifier.getVocabulary();
404            if (result.get(voc) == null){
405                result.put(voc, new ArrayList<Modifier>());
406            }
407            result.get(voc).add(modifier);
408        }
409        return result;
410    }
411
412    public List<Modifier> getModifiers(TermVocabulary voc){
413        List<Modifier> result = makeModifierMap().get(voc);
414        if (result == null){
415            result = new ArrayList<Modifier>();
416        }
417        return result;
418    }
419
420
421
422//************************** CLONE **********************************************************/
423
424    /**
425     * Clones the description element. The element is <b>not</b> added to the same
426     * description as the orginal element (inDescription is set to <code>null</null>).
427     * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
428     */
429    @Override
430    public Object clone() throws CloneNotSupportedException{
431        DescriptionElementBase result = (DescriptionElementBase)super.clone();
432
433        //inDescription
434        result.inDescription = null;
435
436        //Sources
437        result.sources = new HashSet<DescriptionElementSource>();
438        for (DescriptionElementSource source : getSources()){
439            DescriptionElementSource newSource = (DescriptionElementSource)source.clone();
440            result.addSource(newSource);
441        }
442
443        //media
444        result.media = new ArrayList<Media>();
445        for (Media media : getMedia()){
446            result.media.add(media);
447        }
448
449        //modifying text
450        result.modifyingText = new HashMap<Language, LanguageString>();
451        for (Language language : getModifyingText().keySet()){
452            //TODO clone needed? See also IndividualsAssociation
453            LanguageString newLanguageString = (LanguageString)getModifyingText().get(language).clone();
454            result.modifyingText.put(language, newLanguageString);
455        }
456
457        //modifiers
458        result.modifiers = new HashSet<Modifier>();
459        for (Modifier modifier : getModifiers()){
460            result.modifiers.add(modifier);
461        }
462
463        //no changes to: feature
464        return result;
465    }
466
467    /**
468     * Clones the description element.<BR>
469     * The new element is added to the <code>description</code>.<BR>
470     * @see eu.etaxonomy.cdm.model.common.AnnotatableEntity#clone()
471     */
472    public DescriptionElementBase clone(DescriptionBase description) throws CloneNotSupportedException{
473        DescriptionElementBase result = (DescriptionElementBase)clone();
474        description.addElement(result);
475        return result;
476    }
477
478
479}
Note: See TracBrowser for help on using the browser.