Project

General

Profile

Download (15.3 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.name;
11

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

    
15
import javax.persistence.Entity;
16
import javax.persistence.FetchType;
17
import javax.persistence.Inheritance;
18
import javax.persistence.InheritanceType;
19
import javax.persistence.ManyToMany;
20
import javax.persistence.ManyToOne;
21
import javax.persistence.OneToOne;
22
import javax.persistence.Transient;
23
import javax.validation.constraints.NotNull;
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.XmlSeeAlso;
30
import javax.xml.bind.annotation.XmlType;
31

    
32
import org.apache.commons.lang3.StringUtils;
33
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
34
import org.hibernate.annotations.Cascade;
35
import org.hibernate.annotations.CascadeType;
36
import org.hibernate.envers.Audited;
37
import org.hibernate.search.annotations.IndexedEmbedded;
38

    
39
import eu.etaxonomy.cdm.model.common.CdmBase;
40
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
41
import eu.etaxonomy.cdm.model.common.SourcedEntityBase;
42
import eu.etaxonomy.cdm.model.reference.ICdmTarget;
43
import eu.etaxonomy.cdm.model.reference.NamedSource;
44
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
45
import eu.etaxonomy.cdm.model.reference.Reference;
46
import eu.etaxonomy.cdm.validation.Level2;
47
import eu.etaxonomy.cdm.validation.annotation.ValidLectotypeSource;
48
import eu.etaxonomy.cdm.validation.annotation.ValidTypeDesignation;
49

    
50
/**
51
 * The (abstract) class representing a typification of one or several {@link TaxonName taxon names}.<BR>
52
 * All taxon names which have a {@link Rank rank} "species aggregate" or lower
53
 * can only be typified by specimens (a {@link SpecimenTypeDesignation specimen type designation}), but taxon
54
 * names with a higher rank might be typified by an other taxon name with
55
 * rank "species" or "genus" (a {@link NameTypeDesignation name type designation}).
56
 *
57
 * @see		TaxonName
58
 * @see		NameTypeDesignation
59
 * @see		SpecimenTypeDesignation
60
 * @author  a.mueller
61
 * @since 07.08.2008
62
 */
63
@XmlRootElement(name = "TypeDesignationBase")
64
@XmlType(name = "TypeDesignationBase", propOrder = {
65
    "typeStatus",
66
    "notDesignated",
67
    "typifiedNames",
68
    "designationSource",
69
    "registrations",
70
})
71
@XmlSeeAlso({
72
    NameTypeDesignation.class,
73
    SpecimenTypeDesignation.class,
74
    TextualTypeDesignation.class
75
})
76
@Entity
77
@Audited
78
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
79
@ValidTypeDesignation(groups=Level2.class)
80
@ValidLectotypeSource(groups=Level2.class)
81
public abstract class TypeDesignationBase<T extends TypeDesignationStatusBase<T>>
82
        extends SourcedEntityBase<IdentifiableSource>
83
        implements ITypeDesignation {
84

    
85
    private static final long serialVersionUID = 4838214337140859787L;
86

    
87
    @SuppressWarnings("unused")
88
    private static final Logger logger = LogManager.getLogger(TypeDesignationBase.class);
89

    
90
    @XmlElement(name = "IsNotDesignated")
91
    private boolean notDesignated;
92

    
93
    @XmlElement(name = "TypeStatus")
94
    @XmlIDREF
95
    @XmlSchemaType(name = "IDREF")
96
    @ManyToOne(fetch = FetchType.LAZY, targetEntity = TypeDesignationStatusBase.class)
97
    private T typeStatus;
98

    
99
    //the source for the lectotypification (or similar)
100
    @XmlElement(name = "source")
101
    @XmlIDREF
102
    @XmlSchemaType(name = "IDREF")
103
    @OneToOne(fetch = FetchType.LAZY, orphanRemoval=true)
104
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE})
105
    private NamedSource designationSource;
106

    
107
    @XmlElementWrapper(name = "TypifiedNames")
108
    @XmlElement(name = "TypifiedName")
109
    @XmlIDREF
110
    @XmlSchemaType(name = "IDREF")
111
    @ManyToMany(fetch = FetchType.LAZY , mappedBy="typeDesignations")
112
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
113
    private Set<TaxonName> typifiedNames = new HashSet<>();
114

    
115
    //******* REGISTRATION *****************/
116

    
117
    @XmlElementWrapper(name = "Registrations")
118
    @XmlElement(name = "Registration")
119
    @XmlIDREF
120
    @XmlSchemaType(name = "IDREF")
121
    @ManyToMany(mappedBy="typeDesignations", fetch= FetchType.LAZY)
122
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
123
    @NotNull
124
    @IndexedEmbedded(depth=1)
125
    private Set<Registration> registrations = new HashSet<>();
126

    
127

    
128
// **************** CONSTRUCTOR *************************************/
129

    
130
    protected TypeDesignationBase(){
131
        super();
132
    }
133

    
134
    /**
135
     * Class constructor: creates a new type designation
136
     * (including its {@link Reference reference source} and eventually
137
     * the taxon name string originally used by this reference when establishing
138
     * the former designation).
139
     *
140
     * @param citation				the reference source for the new designation
141
     * @param citationMicroReference	the string with the details describing the exact localisation within the reference
142
     * @param originalNameString	the taxon name string used originally in the reference source for the new designation
143
     * @see							#TypeDesignationBase()
144
     * @see							#isNotDesignated()
145
     * @see							TaxonName#getTypeDesignations()
146
     */
147
    protected TypeDesignationBase(Reference citation, String citationMicroReference, String originalNameString) {
148
        this(citation, citationMicroReference, originalNameString, false);
149
    }
150

    
151
    /**
152
     * Class constructor: creates a new type designation
153
     * (including its {@link Reference reference source} and eventually
154
     * the taxon name string originally used by this reference when establishing
155
     * the former designation).
156
     *
157
     * @param citation				the reference source for the new designation
158
     * @param citationMicroReference	the string with the details describing the exact localisation within the reference
159
     * @param originalNameString	the taxon name string used originally in the reference source for the new designation
160
     * @param isNotDesignated		the boolean flag indicating whether there is no type at all for
161
     * 								<i>this</i> type designation
162
     * @see							#TypeDesignationBase()
163
     * @see							#isNotDesignated()
164
     * @see							TaxonName#getTypeDesignations()
165
     */
166
    protected TypeDesignationBase(Reference citation, String citationMicroReference, String originalNameString, boolean notDesignated){
167
        this(NamedSource.NewPrimarySourceInstance(citation, citationMicroReference), originalNameString, notDesignated);
168
    }
169

    
170
    /**
171
     * Class constructor: creates a new type designation
172
     * (including its {@link Reference reference source} and eventually
173
     * the taxon name string originally used by this reference when establishing
174
     * the former designation).
175
     *
176
     * @param source                the reference source for the new designation
177
     * @param originalNameString    the taxon name string used originally in the reference source for the new designation
178
     * @param isNotDesignated       the boolean flag indicating whether there is no type at all for
179
     *                              <i>this</i> type designation
180
     * @see                         #TypeDesignationBase()
181
     * @see                         #isNotDesignated()
182
     * @see                         TaxonName#getTypeDesignations()
183
     */
184
    protected TypeDesignationBase(NamedSource designationSource, String originalNameString, boolean notDesignated){
185
        super();
186
        this.notDesignated = notDesignated;
187
        this.designationSource = designationSource;
188
    }
189

    
190
// **************** METHODS *************************************/
191

    
192
    /**
193
     * Returns the {@link TypeDesignationStatusBase type designation status} for <i>this</i> specimen type
194
     * designation. This status describes which of the possible categories of
195
     * types like "holotype", "neotype", "syntype" or "isotype" applies to <i>this</i>
196
     * specimen type designation.
197
     */
198
    public T getTypeStatus(){
199
        return (CdmBase.deproxy(this.typeStatus));  //otherwise for some error we get an error in TypeDesignationDaoHibernateImplTest
200
    }
201
    /**
202
     * @see  #getTypeStatus()
203
     */
204
    public void setTypeStatus(T typeStatus){
205
        this.typeStatus = typeStatus;
206
    }
207

    
208
    /**
209
     * Returns the boolean value "true" if it is known that a type does not
210
     * exist and therefore the {@link TaxonName taxon name} to which <i>this</i>
211
     * type designation is assigned must still be typified. Two
212
     * cases must be differentiated: <BR>
213
     * <ul>
214
     * <li> a) it is unknown whether a type exists and
215
     * <li> b) it is known that no type exists
216
     * </ul>
217
     * If a) is true there should be no TypeDesignation instance at all
218
     * assigned to the "typified" taxon name.<BR>
219
     * If b) is true there should be a TypeDesignation instance with the
220
     * flag isNotDesignated set. The typeName attribute, in case of a
221
     * {@link NameTypeDesignation name type designation}, or the typeSpecimen attribute,
222
     * in case of a {@link SpecimenTypeDesignation specimen type designation}, should then be "null".
223
     */
224
    public boolean isNotDesignated() {
225
        return notDesignated;
226
    }
227
    /**
228
     * @see   #isNotDesignated()
229
     */
230
    public void setNotDesignated(boolean notDesignated) {
231
        this.notDesignated = notDesignated;
232
    }
233

    
234
    @Transient
235
    public String getCitationMicroReference() {
236
        return designationSource == null ? null : this.designationSource.getCitationMicroReference();
237
    }
238

    
239
    public void setCitationMicroReference(String microReference) {
240
        this.getDesignationSource(true).setCitationMicroReference(StringUtils.isBlank(microReference)? null : microReference);
241
        checkNullSource();
242
    }
243
    /**
244
     * Convenience method to retrieve the reference of the type designations
245
     * designation/lectotype source.
246
     *
247
     * @see #getDesignationSource()
248
     */
249
    @Transient
250
    public Reference getCitation(){
251
        return designationSource == null ? null : this.designationSource.getCitation();
252
    }
253
    /**
254
     * Convenience method to set reference for the designation's
255
     * {@link #getDesignationSource() designation/lectotype source}.
256
     * The source is created if reference is not <code>null</code>
257
     * and the source does not yet exist.
258
     * <BR>
259
     * This field should only be used if
260
     * the {@link #getTypeStatus() status} is lectotype (or similar) which can be
261
     * retrieved by using method {@link TypeDesignationStatusBase#hasDesignationSource()}
262
     *
263
     * @see #getDesignationSource()
264
     */
265
    public void setCitation(Reference citation) {
266
        this.getDesignationSource(true).setCitation(citation);
267
        checkNullSource();
268
    }
269

    
270
    /**
271
     * Returns the {@link #getDesignationSource() designation source}. If a source does not exist
272
     * yet a new and empty one is created. A source should only be created for
273
     * lectotype like type designations (see {@link #getDesignationSource()}.
274
     *
275
     * @param createIfNotExist
276
     * @see #getDesignationSource()
277
     */
278
    public NamedSource getDesignationSource(boolean createIfNotExist) {
279
        if (this.designationSource == null && createIfNotExist){
280
            this.designationSource = NamedSource.NewInstance(OriginalSourceType.PrimaryTaxonomicSource);
281
        }
282
        return designationSource;
283
    }
284

    
285
    /**
286
     * The primary source of typification as used for lecto-, epi- and neotypes.
287
     * This field should only be used if
288
     * the {@link #getTypeStatus() status} is lectotype (or similar) which can be
289
     * retrieved by using method {@link TypeDesignationStatusBase#hasDesignationSource()}.
290
     */
291
    public NamedSource getDesignationSource(){
292
        return designationSource;
293
    }
294
    /**
295
     * @see #getDesignationSource()
296
     */
297
    public void setDesignationSource(NamedSource designationSource) {
298
        this.designationSource = designationSource;
299
    }
300

    
301
    private void checkNullSource() {
302
        if (this.designationSource != null && this.designationSource.checkEmpty(true)){
303
            this.designationSource = null;
304
        }
305
    }
306

    
307
    /**
308
     * Returns the {@link Registration registrations} available for this
309
     * type designation.
310
     */
311
    public Set<Registration> getRegistrations() {
312
        return this.registrations;
313
    }
314

    
315
    /**
316
     * Remove the type (specimen or name) from this type designation
317
     */
318
    public abstract void removeType();
319

    
320
    /**
321
     * Returns the set of {@link TaxonName taxon names} typified in <i>this</i>
322
     * type designation. This is a subset of the taxon names belonging to the
323
     * corresponding {@link #getHomotypicalGroup() homotypical group}.
324
     */
325
    @Override
326
    public Set<TaxonName> getTypifiedNames() {
327
        return typifiedNames;
328
    }
329

    
330
    /**
331
     * @deprecated for bidirectional use only
332
     */
333
    @Deprecated
334
    protected void addTypifiedName(TaxonName taxonName){
335
        this.typifiedNames.add(taxonName);
336
    }
337

    
338
    /**
339
     * @deprecated for bidirectional use only
340
     */
341
    @Deprecated
342
    protected void removeTypifiedName(TaxonName taxonName){
343
        this.typifiedNames.remove(taxonName);
344
        if (taxonName.getTypeDesignations().contains(this)){
345
            taxonName.removeTypeDesignation(this);
346
        }
347
    }
348

    
349
    @Override
350
    protected IdentifiableSource createNewSource(OriginalSourceType type, String idInSource, String idNamespace,
351
            Reference reference, String microReference, String originalInfo, ICdmTarget target) {
352
        return IdentifiableSource.NewInstance(type, idInSource, idNamespace, reference, microReference, originalInfo, target);
353
    }
354

    
355

    
356
    @Override
357
    @Transient
358
    public boolean hasDesignationSource() {
359
        if (getTypeStatus() == null) {
360
            return false;
361
        }
362
        return getTypeStatus().hasDesignationSource();
363
    }
364

    
365
//*********************** CLONE ********************************************************/
366

    
367

    
368
    /**
369
     * Clones <i>this</i> type designation. This is a shortcut that enables to create
370
     * a new instance that differs only slightly from <i>this</i> type designation by
371
     * modifying only some of the attributes.<BR>
372
     * CAUTION: the typifiedNames set is also cloned by adding the new type designation
373
     * to the typifiedNames of the original type designation. If this is unwanted
374
     * th
375
     *
376
     * not cloned but empty after cloning as the typified
377
     * names is considered to be the not owning part of a bidirectional relationship.
378
     * This may be changed in future.
379
     *
380
     * @throws CloneNotSupportedException
381
     *
382
     * @see eu.etaxonomy.cdm.model.common.SourcedEntityBase#clone()
383
     * @see java.lang.Object#clone()
384
     */
385
    @Override
386
    public TypeDesignationBase<T> clone() throws CloneNotSupportedException {
387

    
388
        @SuppressWarnings("unchecked")
389
        TypeDesignationBase<T> result = (TypeDesignationBase<T>)super.clone();
390

    
391
		//registrations
392
		result.registrations = new HashSet<>();
393
		for (Registration registration : registrations){
394
		    registration.addTypeDesignation(result);
395
		}
396

    
397
        //typified names
398
        result.typifiedNames = new HashSet<>();
399
        for (TaxonName taxonName : getTypifiedNames()){
400
            taxonName.addTypeDesignation(result, false);
401
        }
402

    
403
        //no changes to: notDesignated, typeStatus, homotypicalGroup
404
        return result;
405
    }
406
}
(36-36/39)