Project

General

Profile

Download (9.16 KB) Statistics
| Branch: | Tag: | Revision:
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

    
10
package eu.etaxonomy.cdm.model.description;
11

    
12

    
13
import java.util.HashSet;
14
import java.util.Set;
15

    
16
import javax.persistence.Entity;
17
import javax.persistence.FetchType;
18
import javax.persistence.JoinTable;
19
import javax.persistence.ManyToMany;
20
import javax.persistence.ManyToOne;
21
import javax.persistence.Transient;
22
import javax.xml.bind.annotation.XmlAccessType;
23
import javax.xml.bind.annotation.XmlAccessorType;
24
import javax.xml.bind.annotation.XmlElement;
25
import javax.xml.bind.annotation.XmlElementWrapper;
26
import javax.xml.bind.annotation.XmlIDREF;
27
import javax.xml.bind.annotation.XmlRootElement;
28
import javax.xml.bind.annotation.XmlSchemaType;
29
import javax.xml.bind.annotation.XmlType;
30

    
31
import org.apache.log4j.Logger;
32
import org.hibernate.annotations.Cascade;
33
import org.hibernate.annotations.CascadeType;
34
import org.hibernate.envers.Audited;
35
import org.hibernate.search.annotations.FieldBridge;
36
import org.springframework.beans.factory.annotation.Configurable;
37

    
38
import eu.etaxonomy.cdm.hibernate.search.NotNullAwareIdBridge;
39
import eu.etaxonomy.cdm.model.common.CdmBase;
40
import eu.etaxonomy.cdm.model.common.DefinedTerm;
41
import eu.etaxonomy.cdm.model.location.NamedArea;
42
import eu.etaxonomy.cdm.model.taxon.Taxon;
43
import eu.etaxonomy.cdm.strategy.cache.common.IIdentifiableEntityCacheStrategy;
44
import eu.etaxonomy.cdm.strategy.cache.description.TaxonDescriptionDefaultCacheStrategy;
45

    
46
/**
47
 * This class represents descriptions that delimit or circumscribe a real taxon.
48
 * <P>
49
 * This class corresponds to: <ul>
50
 * <li> DescriptionsBaseType with a "Class" element according to the the SDD schema
51
 * <li> SpeciesProfileModel according to the TDWG ontology
52
 * <li> CharacterCircumscription according to the TCS
53
 * </ul>
54
 *
55
 * @author m.doering
56
 * @version 1.0
57
 * @created 08-Nov-2007 13:06:20
58
 */
59
@XmlAccessorType(XmlAccessType.FIELD)
60
@XmlType(name = "TaxonDescription", propOrder = {
61
    "scopes",
62
    "geoScopes",
63
    "taxon"
64
})
65
@XmlRootElement(name = "TaxonDescription")
66
@Entity
67
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
68
//@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionBase")
69
@Audited
70
@Configurable
71
public class TaxonDescription extends DescriptionBase<IIdentifiableEntityCacheStrategy<TaxonDescription>> implements Cloneable{
72
    private static final long serialVersionUID = 8065879180505546803L;
73
    @SuppressWarnings("unused")
74
    private static final Logger logger = Logger.getLogger(TaxonDescription.class);
75

    
76
    @XmlElementWrapper(name = "Scopes")
77
    @XmlElement(name = "Scope")
78
    @XmlIDREF
79
    @XmlSchemaType(name="IDREF")
80
    @ManyToMany(fetch = FetchType.LAZY)
81
    @JoinTable(name="DescriptionBase_Scope")
82
    private Set<DefinedTerm> scopes = new HashSet<DefinedTerm>();
83

    
84
    @XmlElementWrapper( name = "GeoScopes")
85
    @XmlElement( name = "GeoScope")
86
    @XmlIDREF
87
    @XmlSchemaType(name="IDREF")
88
    @ManyToMany(fetch = FetchType.LAZY)
89
    @JoinTable(name="DescriptionBase_GeoScope")
90
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
91
    private Set<NamedArea> geoScopes = new HashSet<NamedArea>();
92

    
93
    @XmlElement( name = "Taxon")
94
    @ManyToOne(fetch = FetchType.LAZY)
95
    @XmlIDREF
96
    @XmlSchemaType(name="IDREF")
97
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
98
    @FieldBridge(impl=NotNullAwareIdBridge.class)
99
    private Taxon taxon;
100

    
101

    
102

    
103
    /**
104
     * Creates a new empty taxon description instance.
105
     *
106
     * @see	#NewInstance(Taxon)
107
     */
108
    public static TaxonDescription NewInstance(){
109
        return new TaxonDescription();
110
    }
111

    
112
    /**
113
     * Creates a new taxon description instance for the given {@link Taxon taxon}.
114
     * The new taxon description will be also added to the {@link Taxon#getDescriptions() set of descriptions}
115
     * assigned to the given taxon.
116
     *
117
     * @see	#NewInstance()
118
     */
119
    public static TaxonDescription NewInstance(Taxon taxon){
120
        TaxonDescription description = new TaxonDescription();
121
        if (taxon != null){
122
            taxon.addDescription(description);
123
        }
124
        return description;
125
    }
126

    
127
    /**
128
     * Creates a new taxon description instance for the given {@link Taxon taxon}.
129
     * The new taxon description will be also added to the {@link Taxon#getDescriptions() set of descriptions}
130
     * assigned to the given taxon.
131
     *
132
     * @see	#NewInstance()
133
     */
134
    public static TaxonDescription NewInstance(Taxon taxon, boolean isImageGallery){
135
        TaxonDescription description = new TaxonDescription();
136
        taxon.addDescription(description);
137
        description.setImageGallery(isImageGallery);
138
        return description;
139
    }
140

    
141
//******************** CONSTRUCTOR *************************************************/
142

    
143
    /**
144
     * Class constructor: creates a new empty taxon description instance.
145
     */
146
    public TaxonDescription(){
147
        super();
148
        this.cacheStrategy = new TaxonDescriptionDefaultCacheStrategy();
149
        }
150

    
151
//************************** METHODS **********************************************/
152

    
153

    
154
    public Taxon getTaxon() {
155
        return taxon;
156
    }
157

    
158

    
159
    protected void setTaxon(Taxon taxon) {
160
    	//TODO needs correct bidirectional handling before making it public
161
    	this.taxon = taxon;
162
    }
163

    
164
    /**
165
     * Returns the set of {@link NamedArea named areas} indicating the geospatial
166
     * data where <i>this</i> taxon description is valid.
167
     */
168
    public Set<NamedArea> getGeoScopes(){
169
        return this.geoScopes;
170
    }
171

    
172
    /**
173
     * Adds a {@link NamedArea named area} to the set of {@link #getGeoScopes() named areas}
174
     * delimiting the geospatial area where <i>this</i> taxon description is valid.
175
     *
176
     * @param geoScope	the named area to be additionally assigned to <i>this</i> taxon description
177
     * @see    	   		#getGeoScopes()
178
     */
179
    public void addGeoScope(NamedArea geoScope){
180
        this.geoScopes.add(geoScope);
181
    }
182

    
183
    /**
184
     * Removes one element from the set of {@link #getGeoScopes() named areas} delimiting
185
     * the geospatial area where <i>this</i> taxon description is valid.
186
     *
187
     * @param  geoScope   the named area which should be removed
188
     * @see     		  #getGeoScopes()
189
     * @see     		  #addGeoScope(NamedArea)
190
     */
191
    public void removeGeoScope(NamedArea geoScope){
192
        this.geoScopes.remove(geoScope);
193
    }
194

    
195

    
196
    /**
197
     * Returns the set of {@link Scope scopes} (this covers mostly {@link Stage life stage} or {@link Sex sex} or both)
198
     * restricting the validity of <i>this</i> taxon description. This set
199
     * of scopes should contain no more than one "sex" and one "life stage".
200
     */
201
    public Set<DefinedTerm> getScopes(){
202
        return this.scopes;
203
    }
204

    
205
    /**
206
     * Adds a {@link Scope scope} (mostly a {@link Stage life stage} or a {@link Sex sex})
207
     * to the set of {@link #getScopes() scopes} restricting the validity of
208
     * <i>this</i> taxon description.
209
     *
210
     * @param scope	the scope to be added to <i>this</i> taxon description
211
     * @see    	   	#getScopes()
212
     */
213
    public void addScope(DefinedTerm scope){
214
        this.scopes.add(scope);
215
    }
216

    
217
    /**
218
     * Removes one element from the set of {@link #getScopes() scopes}
219
     * restricting the validity of <i>this</i> taxon description.
220
     *
221
     * @param  scope	the scope which should be removed
222
     * @see     		#getScopes()
223
     * @see     		#addScope(Scope)
224
     */
225
    public void removeScope(DefinedTerm scope){
226
        this.scopes.remove(scope);
227
    }
228

    
229
    /**
230
     * Returns the first TextData element of feature type image. If no such element exists,
231
     * a new one is created.
232
     * @return
233
     */
234
    @Transient
235
    public TextData getOrCreateImageTextData(){
236
        for (DescriptionElementBase element : this.getElements()){
237
            if (element.getFeature().equals(Feature.IMAGE())){
238
                if (element.isInstanceOf(TextData.class)){
239
                    return CdmBase.deproxy(element, TextData.class);
240
                }
241
            }
242
        }
243
        TextData textData = TextData.NewInstance(Feature.IMAGE());
244
        addElement(textData);
245
        return textData;
246
    }
247

    
248

    
249
//*********************** CLONE ********************************************************/
250

    
251
    /**
252
     * Clones <i>this</i> taxon description. This is a shortcut that enables to create
253
     * a new instance that differs only slightly from <i>this</i> taxon description by
254
     * modifying only some of the attributes.
255
     *
256
     * @see eu.etaxonomy.cdm.model.description.DescriptionBase#clone()
257
     * @see java.lang.Object#clone()
258
     */
259
    @Override
260
    public Object clone() {
261
        TaxonDescription result;
262
        result = (TaxonDescription)super.clone();
263

    
264
        //scopes
265
        result.scopes = new HashSet<DefinedTerm>();
266
        for (DefinedTerm scope : getScopes()){
267
            result.scopes.add(scope);
268
        }
269

    
270
        //geo-scopes
271
        result.geoScopes = new HashSet<NamedArea>();
272
        for (NamedArea namedArea : getGeoScopes()){
273
            result.geoScopes.add(namedArea);
274
        }
275

    
276
        //no changes to: taxon
277
        return result;
278
    }
279

    
280

    
281
}
(29-29/36)