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

Revision 13724, 17.5 kB (checked in by a.kohlbecker, 4 months ago)

hibernate fulltext search & refactoring getTaxaByName*() method headers

  • 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.HashSet;
13import java.util.Set;
14
15import javax.persistence.Entity;
16import javax.persistence.FetchType;
17import javax.persistence.Inheritance;
18import javax.persistence.InheritanceType;
19import javax.persistence.JoinTable;
20import javax.persistence.ManyToMany;
21import javax.persistence.OneToMany;
22import javax.persistence.Transient;
23import javax.xml.bind.annotation.XmlAccessType;
24import javax.xml.bind.annotation.XmlAccessorType;
25import javax.xml.bind.annotation.XmlElement;
26import javax.xml.bind.annotation.XmlElementWrapper;
27import javax.xml.bind.annotation.XmlElements;
28import javax.xml.bind.annotation.XmlIDREF;
29import javax.xml.bind.annotation.XmlSchemaType;
30import javax.xml.bind.annotation.XmlType;
31
32import org.apache.log4j.Logger;
33import org.hibernate.annotations.Cascade;
34import org.hibernate.annotations.CascadeType;
35import org.hibernate.envers.Audited;
36import org.hibernate.search.annotations.ClassBridge;
37import org.hibernate.search.annotations.ContainedIn;
38import org.hibernate.search.annotations.Field;
39
40import eu.etaxonomy.cdm.hibernate.DescriptionBaseClassBridge;
41import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
42import eu.etaxonomy.cdm.model.name.NameRelationship;
43import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
44import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
45import eu.etaxonomy.cdm.model.reference.Reference;
46import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
47
48/**
49 * The upmost (abstract) class for a description as a whole (with possibly
50 * several {@link DescriptionElementBase elementary information data})
51 * for a {@link SpecimenOrObservationBase specimen}, a {@link Taxon taxon}
52 * or even a {@link TaxonNameBase taxon name}.
53 * <P>
54 * This class corresponds to: <ul>
55 * <li> DescriptionsSectionType according to the the SDD schema
56 * <li> MeasurementOrFact according to the ABCD schema
57 * </ul>
58 *
59 * @author m.doering
60 * @version 1.0
61 * @created 08-Nov-2007 13:06:24
62 */
63
64@XmlAccessorType(XmlAccessType.FIELD)
65@XmlType(name = "DescriptionBase", propOrder = {
66    "describedSpecimenOrObservations",
67    "descriptionSources",
68    "descriptiveSystem",
69    "workingSets",
70    "descriptionElements",
71    "imageGallery"
72})
73@Entity
74@Audited
75@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
76@ClassBridge(impl=DescriptionBaseClassBridge.class)
77public abstract class DescriptionBase<S extends IIdentifiableEntityCacheStrategy> extends IdentifiableEntity<S> {
78    private static final long serialVersionUID = 5504218413819040193L;
79    private static final Logger logger = Logger.getLogger(DescriptionBase.class);
80
81    @XmlElementWrapper(name = "DescribedSpecimenOrObservations")
82    @XmlElement(name = "DescribedSpecimenOrObservation")
83    @XmlIDREF
84    @XmlSchemaType(name="IDREF")
85    @ManyToMany(fetch = FetchType.LAZY)
86    @Cascade(CascadeType.SAVE_UPDATE)
87    private Set<SpecimenOrObservationBase> describedSpecimenOrObservations = new HashSet<SpecimenOrObservationBase>();
88
89    @XmlElementWrapper(name = "DescriptionSources")
90    @XmlElement(name = "DescriptionSource")
91    @XmlIDREF
92    @XmlSchemaType(name="IDREF")
93    @ManyToMany(fetch = FetchType.LAZY)  //FIXME what is the difference between this and IdentifiableEntity.sources
94    private Set<Reference> descriptionSources = new HashSet<Reference>();
95
96    @XmlElementWrapper(name = "DescriptiveSystem")
97    @XmlElement(name = "Feature")
98    @XmlIDREF
99    @XmlSchemaType(name="IDREF")
100    @ManyToMany(fetch = FetchType.LAZY)  //FIXME
101    //@Cascade( { CascadeType.SAVE_UPDATE, CascadeType.MERGE })
102    @JoinTable(name = "DescriptionBase_Feature")
103    @Deprecated //will probably be removed in future versions due to #2240
104    //fortunately never worked well due to missing cascade #1846
105    private Set<Feature> descriptiveSystem = new HashSet<Feature>();
106
107    @XmlElementWrapper(name = "WorkingSets")
108    @XmlElement(name = "WorkingSet")
109    @XmlIDREF
110    @XmlSchemaType(name = "IDREF")
111    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "descriptions")
112    @Cascade(CascadeType.SAVE_UPDATE)
113    private Set<WorkingSet> workingSets = new HashSet<WorkingSet>();
114
115    @XmlElementWrapper(name = "DescriptionElements")
116    @XmlElements({
117        @XmlElement(name = "CategorialData", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = CategoricalData.class),
118        @XmlElement(name = "CommonTaxonName", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = CommonTaxonName.class),
119        @XmlElement(name = "Distribution", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = Distribution.class),
120        @XmlElement(name = "IndividualsAssociation", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = IndividualsAssociation.class),
121        @XmlElement(name = "QuantitativeData", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = QuantitativeData.class),
122        @XmlElement(name = "TaxonInteraction", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = TaxonInteraction.class),
123        @XmlElement(name = "TextData", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = TextData.class)
124    })
125    @OneToMany(fetch=FetchType.LAZY, mappedBy = "inDescription")
126    @Cascade( { CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE, CascadeType.DELETE_ORPHAN })
127    @ContainedIn
128    private Set<DescriptionElementBase> descriptionElements = new HashSet<DescriptionElementBase>();
129
130    @XmlElement(name = "ImageGallery")
131    private boolean imageGallery;
132
133
134    /**
135     * Returns the set of {@link SpecimenOrObservationBase specimens or observations} involved in
136     * <i>this</i> description as a whole. {@link TaxonDescription Taxon descriptions} are also often based
137     * on concrete specimens or observations. For {@link TaxonNameDescription taxon name descriptions}
138     * this set should be empty.
139     *
140     * @see    #addDescribedSpecimenOrObservations(SpecimenOrObservationBase)
141     * @see    #removeDescribedSpecimenOrObservations(SpecimenOrObservationBase)
142     */
143    public Set<SpecimenOrObservationBase> getDescribedSpecimenOrObservations() {
144        return describedSpecimenOrObservations;
145    }
146
147    /**
148     * Adds an existing {@link SpecimenOrObservationBase specimen or observation} to the set of
149     * {@link #getDescribedSpecimenOrObservations() specimens or observations} described in <i>this</i>
150     * description or which <i>this</i> description is based on.<BR>
151     * Due to bidirectionality if <i>this</i> description is a {@link SpecimenDescription specimen description},
152     * <i>this</i> description will also be added to the set of specimen
153     * descriptions corresponding to the given additional specimen or observation.
154     *
155     * @param describedSpecimenOrObservation    the specimen or observation to be added to <i>this</i> description
156     * @see                                                                     #getDescribedSpecimenOrObservations()
157     * @see                                                                     SpecimenOrObservationBase#addDescription(DescriptionBase)
158     */
159    public void addDescribedSpecimenOrObservation(SpecimenOrObservationBase describedSpecimenOrObservation) {
160        logger.debug("addDescribedSpecimenOrObservations");
161        this.describedSpecimenOrObservations.add(describedSpecimenOrObservation);
162        if (! describedSpecimenOrObservation.getDescriptions().contains(this)){
163            describedSpecimenOrObservation.addDescription(this);
164        }
165    }
166
167    /**
168     * Removes one element from the set of {@link #getDescribedSpecimenOrObservations() specimens or observations} involved
169     * in <i>this</i> description.<BR>
170     * Due to bidirectionality if <i>this</i> description is a {@link SpecimenDescription specimen description},
171     * <i>this</i> description will also be removed from the set of specimen
172     * descriptions corresponding to the given specimen or observation.
173     *
174     * @param  describedSpecimenOrObservation   the specimen or observation which should be removed
175     * @see                                                                     #getDescribedSpecimenOrObservations()
176     * @see                                                                     #addDescribedSpecimenOrObservations(SpecimenOrObservationBase)
177     * @see                                                                     SpecimenOrObservationBase#removeDescription(DescriptionBase)
178     */
179    public void removeDescribedSpecimenOrObservation(SpecimenOrObservationBase describedSpecimenOrObservation) {
180        this.describedSpecimenOrObservations.remove(describedSpecimenOrObservation);
181        if (describedSpecimenOrObservation.getDescriptions().contains(this)){
182            describedSpecimenOrObservation.removeDescription(this);
183        }
184    }
185
186    /**
187     * Returns the set of {@link Reference references} used as sources for <i>this</i> description as a
188     * whole. More than one source can be used for a general description without
189     * assigning for each data element of the description one of those sources.
190     *
191     * @see    #addDescriptionSource(Reference)
192     * @see    #removeDescriptionSource(Reference)
193     */
194    @Deprecated //will probably be removed in future versions due to #2240
195    public Set<Reference> getDescriptionSources() {
196        return this.descriptionSources;
197    }
198
199    /**
200     * Adds an existing {@link Reference reference} to the set of
201     * {@link #getDescriptionSources() references} used as sources for <i>this</i>
202     * description.
203     *
204     * @param descriptionSource the reference source to be added to <i>this</i> description
205     * @see                                     #getDescriptionSources()
206     */
207    @Deprecated //will probably be removed in future versions due to #2240
208    public void addDescriptionSource(Reference descriptionSource) {
209        this.descriptionSources.add(descriptionSource);
210    }
211
212    /**
213     * Removes one element from the set of {@link #getDescriptionSources() references} used as
214     * sources for <i>this</i> description.
215     *
216     * @param  descriptionSource        the reference source which should be deleted
217     * @see                                             #getDescriptionSources()
218     * @see                                             #addDescriptionSource(Reference)
219     */
220    @Deprecated //will probably be removed in future versions due to #2240
221    public void removeDescriptionSource(Reference descriptionSource) {
222        this.descriptionSources.remove(descriptionSource);
223    }
224
225    /**
226     * Returns the set of {@link Feature feature} used as
227     * features/characters/descriptors for <i>this</i> description.
228     *
229     * @see    #addFeature(Feature)
230     * @see    #removeFeature(Feature)
231     */
232    public Set<Feature> getDescriptiveSystem() {
233        return this.descriptiveSystem;
234    }
235
236    /**
237     * @see    #getDescriptiveSystem()
238     * @see    #addDescriptiveSystem(Feature)
239     */
240    public void setDescriptiveSystem(Set<Feature> descriptiveSystem) {
241        this.descriptiveSystem = descriptiveSystem;
242    }
243
244    /**
245     * Adds an existing {@link Feature feature} to the set of
246     * {@link #getDescriptiveSystem() descriptiveSystem} used as features for
247     * <i>this</i> description.
248     *
249     * @param feature   the feature to be added to the descriptive system
250     * @see     #getDescriptiveSystem()
251     */
252    public void addFeature(Feature feature) {
253        this.descriptiveSystem.add(feature);
254    }
255
256    /**
257     * Removes one element from the set of {@link #getDescriptiveSystem() features} used as
258     * features for <i>this</i> description.
259     *
260     * @param  feature  the feature which should be deleted
261     * @see     #getDescriptiveSystem()
262     * @see     addFeature(Feature)
263     */
264    public void removeFeature(Feature feature) {
265        this.descriptiveSystem.remove(feature);
266    }
267
268    /**
269     * Returns the set of {@link DescriptionElementBase elementary description data} which constitute
270     * <i>this</i> description as a whole.
271     *
272     * @see    #addElement(DescriptionElementBase)
273     * @see    #removeElement(DescriptionElementBase)
274     */
275    public Set<DescriptionElementBase> getElements() {
276        return this.descriptionElements;
277    }
278
279    /**
280     * Adds an existing {@link DescriptionElementBase elementary description} to the set of
281     * {@link #getElements() elementary description data} which constitute <i>this</i>
282     * description as a whole.
283     * If the elementary descriptions already belongs to a description it is first removed from
284     * the old description.
285     *
286     * @param element   the elementary description to be added to <i>this</i> description
287     * @see                     #getDescriptionSources()
288     */
289    public void addElement(DescriptionElementBase element) {
290        if (element.getInDescription() != null){
291            element.getInDescription().removeElement(element);
292        }
293        element.setInDescription(this);
294        this.descriptionElements.add(element);
295    }
296
297    /**
298     * Removes one element from the set of {@link #getElements() elementary description data} which
299     * constitute <i>this</i> description as a whole.
300     *
301     * @param  element  the reference source which should be deleted
302     * @see                     #getElements()
303     * @see                     #addElement(DescriptionElementBase)
304     */
305    public void removeElement(DescriptionElementBase element) {
306        this.descriptionElements.remove(element);
307        element.setInDescription(null);
308    }
309
310    /**
311     * Returns the number of {@link DescriptionElementBase elementary description data} which constitute
312     * <i>this</i> description as a whole. This is the cardinality of the set of
313     * elementary description data.
314     *
315     * @see             #getElements()
316     * @return  the number of elements of the elementary description data set
317     */
318    public int size(){
319        return this.descriptionElements.size();
320    }
321
322    /**
323     * @return the imageGallery
324     */
325    public boolean isImageGallery() {
326        return imageGallery;
327    }
328
329    /**
330     * @param imageGallery the imageGallery to set
331     */
332    public void setImageGallery(boolean imageGallery) {
333        this.imageGallery = imageGallery;
334    }
335
336
337    public Set<WorkingSet> getWorkingSets() {
338        return workingSets;
339    }
340
341    public boolean addWorkingSet(WorkingSet workingSet){
342        boolean result = this.workingSets.add(workingSet);
343        if (! workingSet.getDescriptions().contains(this)){
344            workingSet.addDescription(this);
345        }
346        return result;
347    }
348
349    public boolean removeWorkingSet(WorkingSet workingSet){
350        boolean result = this.workingSets.remove(workingSet);
351        if (workingSet.getDescriptions().contains(this)){
352            workingSet.addDescription(this);
353        }
354        return result;
355    }
356
357    protected void setWorkingSets(Set<WorkingSet> workingSets) {
358        this.workingSets = workingSets;
359    }
360
361
362
363    @Transient
364    public boolean hasStructuredData(){
365        for (DescriptionElementBase element : this.getElements()){
366            if (element.isInstanceOf(QuantitativeData.class) ||
367                    element.isInstanceOf(CategoricalData.class)){
368                return true;
369            }
370        }
371        return false;
372    }
373
374
375//*********************** CLONE ********************************************************/
376
377    /**
378     * Clones <i>this</i> descriptioin. This is a shortcut that enables to create
379     * a new instance that differs only slightly from <i>this</i> description by
380     * modifying only some of the attributes.<BR>
381     *
382     * Usages of this name in a taxon concept are NOT cloned.<BR>
383     * The name is added to the same homotypical group as the original name
384     * (CAUTION: this behaviour needs to be discussed and may change in future).<BR>
385     * {@link TaxonNameDescription Name descriptions} are cloned as XXX.<BR>
386     * {@link TypeDesignationBase Type designations} are cloned as XXX.<BR>
387     * {@link NameRelationship Name relation} are cloned as XXX.<BR>
388     *
389     * @see eu.etaxonomy.cdm.model.media.IdentifiableEntity#clone()
390     * @see java.lang.Object#clone()
391     */
392    @Override
393    public Object clone()  {
394        DescriptionBase result;
395        try{
396            result = (DescriptionBase)super.clone();
397
398            //descriptive system
399            result.descriptiveSystem = new HashSet<Feature>();
400            for (Feature feature : getDescriptiveSystem()){
401                result.descriptiveSystem.add(feature);
402            }
403
404            //working set
405            result.workingSets = new HashSet<WorkingSet>();
406            for (WorkingSet workingSet : getWorkingSets()){
407                workingSet.addDescription(result);
408            }
409
410            //descriptions
411            result.descriptionSources = new HashSet<Reference>();
412            for (Reference reference : getDescriptionSources()){
413                result.descriptionSources.add(reference);
414            }
415
416            //elements
417            result.descriptionElements = new HashSet<DescriptionElementBase>();
418            for (DescriptionElementBase element : getElements()){
419                DescriptionElementBase newElement = (DescriptionElementBase)element.clone();
420                result.addElement(newElement);
421            }
422
423            //specimen or observations
424            result.describedSpecimenOrObservations = new HashSet<SpecimenOrObservationBase>();
425            for (SpecimenOrObservationBase specimenOrObservation : getDescribedSpecimenOrObservations()){
426                specimenOrObservation.addDescription(result);
427            }
428
429            //no changes to: imageGallery
430            return result;
431        } catch (CloneNotSupportedException e) {
432            logger.warn("Object does not implement cloneable");
433            e.printStackTrace();
434            return null;
435        }
436
437    }
438}
Note: See TracBrowser for help on using the browser.