Project

General

Profile

Download (38 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.HashMap;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import javax.persistence.Entity;
21
import javax.persistence.FetchType;
22
import javax.persistence.JoinColumn;
23
import javax.persistence.JoinTable;
24
import javax.persistence.ManyToMany;
25
import javax.persistence.OneToMany;
26
import javax.persistence.Transient;
27
import javax.xml.bind.annotation.XmlAccessType;
28
import javax.xml.bind.annotation.XmlAccessorType;
29
import javax.xml.bind.annotation.XmlElement;
30
import javax.xml.bind.annotation.XmlElementWrapper;
31
import javax.xml.bind.annotation.XmlIDREF;
32
import javax.xml.bind.annotation.XmlRootElement;
33
import javax.xml.bind.annotation.XmlSchemaType;
34
import javax.xml.bind.annotation.XmlType;
35

    
36
import org.apache.log4j.Logger;
37
import org.hibernate.annotations.Cascade;
38
import org.hibernate.annotations.CascadeType;
39
import org.hibernate.envers.Audited;
40

    
41
import eu.etaxonomy.cdm.model.common.DefinedTerm;
42
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
43
import eu.etaxonomy.cdm.model.common.Language;
44
import eu.etaxonomy.cdm.model.common.Representation;
45
import eu.etaxonomy.cdm.model.common.TermType;
46
import eu.etaxonomy.cdm.model.common.TermVocabulary;
47
import eu.etaxonomy.cdm.model.name.BotanicalName;
48
import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
49
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
50
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
51
import eu.etaxonomy.cdm.model.taxon.Taxon;
52

    
53

    
54
/**
55
 * The class for individual properties (also designed as character, type or
56
 * category) of observed phenomena able to be described or measured. It also
57
 * covers categories of informations on {@link TaxonNameBase taxon names} not
58
 * taken in account in {@link NomenclaturalCode nomenclature}.<BR>
59
 * Descriptions require features in order to be structured and disaggregated
60
 * in {@link DescriptionElementBase description elements}.<BR>
61
 * Experts do not use the word feature for the actual description
62
 * but only for the property itself. Therefore naming this class FeatureType
63
 * would have leaded to confusion.
64
 * <P>
65
 * Since features are {@link DefinedTermBase defined terms} they have a hierarchical
66
 * structure that allows to specify ("kind of") or generalize
67
 * ("generalization of") features. "Kind of" / "generalization of" relations
68
 * are bidirectional (a feature F1 is a "Kind of" a feature F2 if and only
69
 * if the feature F2 is a "generalization of" the feature F1. This hierarchical
70
 * structure has nothing in common with {@link FeatureTree feature trees} used for determination.
71
 * <P>
72
 * A standard set of feature instances will be automatically
73
 * created as the project starts. But this class allows to extend this standard
74
 * set by creating new instances of additional features if needed.<BR>
75
 * <P>
76
 * This class corresponds to DescriptionsSectionType according to the SDD
77
 * schema.
78
 *
79
 * @author m.doering
80
 * @created 08-Nov-2007 13:06:24
81
 */
82
@XmlAccessorType(XmlAccessType.PROPERTY)
83
@XmlType(name="Feature", factoryMethod="NewInstance", propOrder = {
84
		"kindOf",
85
		"generalizationOf",
86
		"partOf",
87
		"includes",
88
	    "supportsTextData",
89
	    "supportsQuantitativeData",
90
	    "supportsDistribution",
91
	    "supportsIndividualAssociation",
92
	    "supportsTaxonInteraction",
93
	    "supportsCommonTaxonName",
94
	    "supportsCategoricalData",
95
	    "recommendedModifierEnumeration",
96
	    "recommendedStatisticalMeasures",
97
	    "supportedCategoricalEnumerations",
98
	    "recommendedMeasurementUnits"
99
})
100
@XmlRootElement(name = "Feature")
101
@Entity
102
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
103
//@Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
104
@Audited
105
public class Feature extends DefinedTermBase<Feature> {
106
	private static final long serialVersionUID = 6754598791831848704L;
107
	private static final Logger logger = Logger.getLogger(Feature.class);
108

    
109
	protected static Map<UUID, Feature> termMap = null;
110

    
111
	private boolean supportsTextData = true;   //by default text data should be always supported
112

    
113
	private boolean supportsQuantitativeData;
114

    
115
	private boolean supportsDistribution;
116

    
117
	private boolean supportsIndividualAssociation;
118

    
119
	private boolean supportsTaxonInteraction;
120

    
121
	private boolean supportsCategoricalData;
122

    
123
	private boolean supportsCommonTaxonName;
124

    
125
    /* for M:M see #4843 */
126
	@ManyToMany(fetch = FetchType.LAZY)
127
    @JoinTable(name="DefinedTermBase_RecommendedModifierEnumeration")
128
	private final Set<TermVocabulary<DefinedTerm>> recommendedModifierEnumeration = new HashSet<TermVocabulary<DefinedTerm>>();
129

    
130
	@ManyToMany(fetch = FetchType.LAZY)
131
    @JoinTable(name="DefinedTermBase_StatisticalMeasure")
132
	private final Set<StatisticalMeasure> recommendedStatisticalMeasures = new HashSet<StatisticalMeasure>();
133

    
134
	/* for M:M see #4843 */
135
	@ManyToMany(fetch = FetchType.LAZY)
136
	@JoinTable(name="DefinedTermBase_SupportedCategoricalEnumeration")
137
	private final Set<TermVocabulary<State>> supportedCategoricalEnumerations = new HashSet<TermVocabulary<State>>();
138

    
139

    
140
	@ManyToMany(fetch = FetchType.LAZY)
141
    @JoinTable(name="DefinedTermBase_MeasurementUnit")
142
	private final Set<MeasurementUnit> recommendedMeasurementUnits = new HashSet<MeasurementUnit>();
143

    
144

    
145
    //copy from RelationshipTermBase
146
	@XmlElementWrapper(name = "InverseRepresentations")
147
    @XmlElement(name = "Representation")
148
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
149
    @JoinTable(name="RelationshipTermBase_inverseRepresentation",
150
            joinColumns=@JoinColumn(name="relationshiptermbase_id")
151
    )
152
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
153
//    @IndexedEmbedded(depth = 2)
154
    private Set<Representation> inverseRepresentations = new HashSet<Representation>();
155

    
156
    private static final UUID uuidUnknown = UUID.fromString("910307f1-dc3c-452c-a6dd-af5ac7cd365c");
157
    private static final UUID uuidDescription = UUID.fromString("9087cdcd-8b08-4082-a1de-34c9ba9fb493");
158
    private static final UUID uuidDistribution = UUID.fromString("9fc9d10c-ba50-49ee-b174-ce83fc3f80c6");
159
    private static final UUID uuidEcology = UUID.fromString("aa923827-d333-4cf5-9a5f-438ae0a4746b");
160
    private static final UUID uuidHabitat = UUID.fromString("fb16929f-bc9c-456f-9d40-dec987b36438");
161
    private static final UUID uuidHabitatAndEcology = UUID.fromString("9fdc4663-4d56-47d0-90b5-c0bf251bafbb");
162
    private static final UUID uuidChromosomeNumber = UUID.fromString("6f677e98-d8d5-4bc5-80bf-affdb7e3945a");
163

    
164
    private static final UUID uuidBiologyEcology = UUID.fromString("9832e24f-b670-43b4-ac7c-20a7261a1d8c");
165
    private static final UUID uuidKey = UUID.fromString("a677f827-22b9-4205-bb37-11cb48dd9106");
166
    private static final UUID uuidMaterialsExamined = UUID.fromString("7c0c7571-a864-47c1-891d-01f59000dae1");
167
    private static final UUID uuidMaterialsMethods = UUID.fromString("1e87d9c3-0844-4a03-9686-773e2ccb3ab6");
168
    private static final UUID uuidEtymology = UUID.fromString("dd653d48-355c-4aec-a4e7-724f6eb29f8d");
169
    private static final UUID uuidDiagnosis = UUID.fromString("d43d8501-ceab-4caa-9e51-e87138528fac");
170
    private static final UUID uuidProtologue = UUID.fromString("71b356c5-1e3f-4f5d-9b0f-c2cf8ae7779f");
171
    private static final UUID uuidCommonName = UUID.fromString("fc810911-51f0-4a46-ab97-6562fe263ae5");
172
    private static final UUID uuidPhenology = UUID.fromString("a7786d3e-7c58-4141-8416-346d4c80c4a2");
173
    private static final UUID uuidOccurrence = UUID.fromString("5deff505-1a32-4817-9a74-50e6936fd630");
174
    private static final UUID uuidCitation = UUID.fromString("99b2842f-9aa7-42fa-bd5f-7285311e0101");
175
    private static final UUID uuidAdditionalPublication = UUID.fromString("2c355c16-cb04-4858-92bf-8da8d56dea95");
176
    private static final UUID uuidUses = UUID.fromString("e5374d39-b210-47c7-bec1-bee05b5f1cb6");
177
    private static final UUID uuidConservation = UUID.fromString("4518fc20-2492-47de-b345-777d2b83c9cf");
178
    private static final UUID uuidCultivation = UUID.fromString("e28965b2-a367-48c5-b954-8afc8ac2c69b");
179
    private static final UUID uuidIntroduction = UUID.fromString("e75255ca-8ff4-4905-baad-f842927fe1d3");
180
    private static final UUID uuidDiscussion = UUID.fromString("d3c4cbb6-0025-4322-886b-cd0156753a25");
181
    private static final UUID uuidImage = UUID.fromString("84193b2c-327f-4cce-90ef-c8da18fd5bb5");
182
    private static final UUID uuidAnatomy = UUID.fromString("94213b2c-e67a-4d37-25ef-e8d316edfba1");
183
    private static final UUID uuidHostPlant = UUID.fromString("6e9de1d5-05f0-40d5-8786-2fe30d0d894d");
184
    private static final UUID uuidPathogenAgent = UUID.fromString("002d05f2-fd72-49f1-ba4d-196cf09240b5");
185
    private static final UUID uuidIndividualsAssociation = UUID.fromString("e2308f37-ddc5-447d-b483-5e2171dd85fd");
186
    private static final UUID uuidSpecimen = UUID.fromString("8200e050-d5fd-4cac-8a76-4b47afb13809");
187
    private static final UUID uuidObservation = UUID.fromString("f59e747d-0b4f-4bf7-b69a-cbd50bc78595");
188
    private static final UUID uuidStatus = UUID.fromString("86d40635-2a63-4ad6-be75-9faa4a6a57fb");
189
    private static final UUID uuidSystematics = UUID.fromString("bd9aca17-cd0e-4418-a3a1-1a4b80dbc162");
190
    private static final UUID uuidUseRecord = UUID.fromString("8125a59d-b4d5-4485-89ea-67306297b599");
191

    
192

    
193
/* ***************** CONSTRUCTOR AND FACTORY METHODS **********************************/
194

    
195
	/**
196
	 * Class constructor: creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
197
	 * a label and a label abbreviation.
198
	 *
199
	 * @param	term  		 the string (in the default language) describing the
200
	 * 						 new feature to be created
201
	 * @param	label  		 the string identifying the new feature to be created
202
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
203
	 * 						 new feature to be created
204
	 * @see 				 #Feature()
205
	 */
206
	protected Feature(String term, String label, String labelAbbrev) {
207
		super(TermType.Feature, term, label, labelAbbrev);
208
	}
209

    
210
	/**
211
	 * Creates a new empty feature instance.
212
	 *
213
	 * @see #NewInstance(String, String, String)
214
	 */
215
	public static Feature NewInstance() {
216
		return new Feature();
217
	}
218

    
219
	/**
220
	 * Creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
221
	 * a label and a label abbreviation.
222
	 *
223
	 * @param	term  		 the string (in the default language) describing the
224
	 * 						 new feature to be created
225
	 * @param	label  		 the string identifying the new feature to be created
226
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
227
	 * 						 new feature to be created
228
	 * @see 				 #readCsvLine(List, Language)
229
	 * @see 				 #NewInstance()
230
	 */
231
	public static Feature NewInstance(String term, String label, String labelAbbrev){
232
		return new Feature(term, label, labelAbbrev);
233
	}
234

    
235

    
236
    //for hibernate use only
237
    @Deprecated
238
    protected Feature() {
239
        super(TermType.Feature);
240
    }
241

    
242
/* *************************************************************************************/
243

    
244
	@Override
245
	public void resetTerms(){
246
		termMap = null;
247
	}
248

    
249

    
250
	/**
251
	 * Returns the boolean value of the flag indicating whether <i>this</i>
252
	 * feature can be described with {@link QuantitativeData quantitative data} (true)
253
	 * or not (false). If this flag is set <i>this</i> feature can only apply to
254
	 * {@link TaxonDescription taxon descriptions} or {@link SpecimenDescription specimen descriptions}.
255
	 *
256
	 * @return  the boolean value of the supportsQuantitativeData flag
257
	 */
258
	@XmlElement(name = "SupportsQuantitativeData")
259
	public boolean isSupportsQuantitativeData() {
260
		return supportsQuantitativeData;
261
	}
262

    
263
	/**
264
	 * @see	#isSupportsQuantitativeData()
265
	 */
266
	public void setSupportsQuantitativeData(boolean supportsQuantitativeData) {
267
		this.supportsQuantitativeData = supportsQuantitativeData;
268
	}
269

    
270
	/**
271
	 * Returns the boolean value of the flag indicating whether <i>this</i>
272
	 * feature can be described with {@link TextData text data} (true)
273
	 * or not (false).
274
	 *
275
	 * @return  the boolean value of the supportsTextData flag
276
	 */
277
	@XmlElement(name = "SupportsTextData")
278
	public boolean isSupportsTextData() {
279
		return supportsTextData;
280
	}
281

    
282
	/**
283
	 * @see	#isSupportsTextData()
284
	 */
285
	public void setSupportsTextData(boolean supportsTextData) {
286
		this.supportsTextData = supportsTextData;
287
	}
288

    
289
	/**
290
	 * Returns the boolean value of the flag indicating whether <i>this</i>
291
	 * feature can be described with {@link Distribution distribution} objects
292
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
293
	 * is the {@link #DISTRIBUTION() distribution feature}.
294
	 *
295
	 * @return  the boolean value of the supportsDistribution flag
296
	 */
297
	@XmlElement(name = "SupportsDistribution")
298
	public boolean isSupportsDistribution() {
299
		return supportsDistribution;
300
	}
301

    
302
	/**
303
	 * @see	#isSupportsDistribution()
304
	 */
305
	public void setSupportsDistribution(boolean supportsDistribution) {
306
		this.supportsDistribution = supportsDistribution;
307
	}
308

    
309
	/**
310
	 * Returns the boolean value of the flag indicating whether <i>this</i>
311
	 * feature can be described with {@link IndividualsAssociation individuals associations}
312
	 * (true) or not (false).
313
	 *
314
	 * @return  the boolean value of the supportsIndividualAssociation flag
315
	 */
316
	@XmlElement(name = "SupportsIndividualAssociation")
317
	public boolean isSupportsIndividualAssociation() {
318
		return supportsIndividualAssociation;
319
	}
320

    
321
	/**
322
	 * @see	#isSupportsIndividualAssociation()
323
	 */
324
	public void setSupportsIndividualAssociation(
325
			boolean supportsIndividualAssociation) {
326
		this.supportsIndividualAssociation = supportsIndividualAssociation;
327
	}
328

    
329
	/**
330
	 * Returns the boolean value of the flag indicating whether <i>this</i>
331
	 * feature can be described with {@link TaxonInteraction taxon interactions}
332
	 * (true) or not (false).
333
	 *
334
	 * @return  the boolean value of the supportsTaxonInteraction flag
335
	 */
336
	@XmlElement(name = "SupportsTaxonInteraction")
337
	public boolean isSupportsTaxonInteraction() {
338
		return supportsTaxonInteraction;
339
	}
340

    
341
	/**
342
	 * @see	#isSupportsTaxonInteraction()
343
	 */
344
	public void setSupportsTaxonInteraction(boolean supportsTaxonInteraction) {
345
		this.supportsTaxonInteraction = supportsTaxonInteraction;
346
	}
347

    
348
	/**
349
	 * Returns the boolean value of the flag indicating whether <i>this</i>
350
	 * feature can be described with {@link CommonTaxonName common names}
351
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
352
	 * is the {@link #COMMON_NAME() common name feature}.
353
	 *
354
	 * @return  the boolean value of the supportsCommonTaxonName flag
355
	 */
356
	@XmlElement(name = "SupportsCommonTaxonName")
357
	public boolean isSupportsCommonTaxonName() {
358
		return supportsCommonTaxonName;
359
	}
360

    
361
	/**
362
	 * @see	#isSupportsTaxonInteraction()
363
	 */
364
	public void setSupportsCommonTaxonName(boolean supportsCommonTaxonName) {
365
		this.supportsCommonTaxonName = supportsCommonTaxonName;
366
	}
367

    
368
	/**
369
	 * Returns the boolean value of the flag indicating whether <i>this</i>
370
	 * feature can be described with {@link CategoricalData categorical data}
371
	 * (true) or not (false).
372
	 *
373
	 * @return  the boolean value of the supportsCategoricalData flag
374
	 */
375
	@XmlElement(name = "SupportsCategoricalData")
376
	public boolean isSupportsCategoricalData() {
377
		return supportsCategoricalData;
378
	}
379

    
380
	/**
381
	 * @see	#supportsCategoricalData()
382
	 */
383
	public void setSupportsCategoricalData(boolean supportsCategoricalData) {
384
		this.supportsCategoricalData = supportsCategoricalData;
385
	}
386

    
387

    
388
	/**
389
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the
390
	 * {@link Modifier modifiers} recommended to be used for {@link DescriptionElementBase description elements}
391
	 * with <i>this</i> feature.
392
	 *
393
	 */
394
	@XmlElementWrapper(name = "RecommendedModifierEnumerations")
395
	@XmlElement(name = "RecommendedModifierEnumeration")
396
	@XmlIDREF
397
	@XmlSchemaType(name = "IDREF")
398
	public Set<TermVocabulary<DefinedTerm>> getRecommendedModifierEnumeration() {
399
		return recommendedModifierEnumeration;
400
	}
401

    
402
	/**
403
	 * Adds a {@link TermVocabulary term vocabulary} (with {@link Modifier modifiers}) to the set of
404
	 * {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies} assigned
405
	 * to <i>this</i> feature.
406
	 *
407
	 * @param recommendedModifierEnumeration	the term vocabulary to be added
408
	 * @see    	   								#getRecommendedModifierEnumeration()
409
	 */
410
	public void addRecommendedModifierEnumeration(
411
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
412
		this.recommendedModifierEnumeration.add(recommendedModifierEnumeration);
413
	}
414
	/**
415
	 * Removes one element from the set of {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies}
416
	 * assigned to <i>this</i> feature.
417
	 *
418
	 * @param  recommendedModifierEnumeration	the term vocabulary which should be removed
419
	 * @see     								#getRecommendedModifierEnumeration()
420
	 * @see     								#addRecommendedModifierEnumeration(TermVocabulary)
421
	 */
422
	public void removeRecommendedModifierEnumeration(
423
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
424
		this.recommendedModifierEnumeration.remove(recommendedModifierEnumeration);
425
	}
426

    
427
	/**
428
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
429
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
430
	 */
431
	@XmlElementWrapper(name = "RecommendedStatisticalMeasures")
432
	@XmlElement(name = "RecommendedStatisticalMeasure")
433
	@XmlIDREF
434
	@XmlSchemaType(name = "IDREF")
435
	public Set<StatisticalMeasure> getRecommendedStatisticalMeasures() {
436
		return recommendedStatisticalMeasures;
437
	}
438

    
439
	/**
440
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
441
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
442
	 * to <i>this</i> feature.
443
	 *
444
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
445
	 * @see    	   							#getRecommendedStatisticalMeasures()
446
	 */
447
	public void addRecommendedStatisticalMeasure(
448
			StatisticalMeasure recommendedStatisticalMeasure) {
449
		this.recommendedStatisticalMeasures.add(recommendedStatisticalMeasure);
450
	}
451
	/**
452
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
453
	 * assigned to <i>this</i> feature.
454
	 *
455
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
456
	 * @see     								#getRecommendedStatisticalMeasures()
457
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
458
	 */
459
	public void removeRecommendedStatisticalMeasure(
460
			StatisticalMeasure recommendedStatisticalMeasure) {
461
		this.recommendedStatisticalMeasures.remove(recommendedStatisticalMeasure);
462
	}
463

    
464
	/**
465
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
466
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
467
	 */
468
	@XmlElementWrapper(name = "RecommendedMeasurementUnits")
469
	@XmlElement(name = "RecommendedMeasurementUnit")
470
	@XmlIDREF
471
	@XmlSchemaType(name = "IDREF")
472
	public Set<MeasurementUnit> getRecommendedMeasurementUnits() {
473
		return recommendedMeasurementUnits;
474
	}
475

    
476
	/**
477
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
478
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
479
	 * to <i>this</i> feature.
480
	 *
481
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
482
	 * @see    	   							#getRecommendedStatisticalMeasures()
483
	 */
484
	public void addRecommendedMeasurementUnit(
485
			MeasurementUnit recommendedMeasurementUnit) {
486
		this.recommendedMeasurementUnits.add(recommendedMeasurementUnit);
487
	}
488
	/**
489
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
490
	 * assigned to <i>this</i> feature.
491
	 *
492
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
493
	 * @see     								#getRecommendedStatisticalMeasures()
494
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
495
	 */
496
	public void removeRecommendedMeasurementUnit(
497
			MeasurementUnit recommendedMeasurementUnit) {
498
		this.recommendedMeasurementUnits.remove(recommendedMeasurementUnit);
499
	}
500

    
501
	/**
502
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the list of
503
	 * possible {@link State states} to be used in {@link CategoricalData categorical data}
504
	 * with <i>this</i> feature.
505
	 *
506
	 */
507
	@XmlElementWrapper(name = "SupportedCategoricalEnumerations")
508
	@XmlElement(name = "SupportedCategoricalEnumeration")
509
	@XmlIDREF
510
	@XmlSchemaType(name = "IDREF")
511
	public Set<TermVocabulary<State>> getSupportedCategoricalEnumerations() {
512
		return supportedCategoricalEnumerations;
513
	}
514

    
515
	/**
516
	 * Adds a {@link TermVocabulary term vocabulary} to the set of
517
	 * {@link #getSupportedCategoricalEnumerations() supported state vocabularies} assigned
518
	 * to <i>this</i> feature.
519
	 *
520
	 * @param supportedCategoricalEnumeration	the term vocabulary which should be removed
521
	 * @see    	   								#getSupportedCategoricalEnumerations()
522
	 */
523
	public void addSupportedCategoricalEnumeration(
524
			TermVocabulary<State> supportedCategoricalEnumeration) {
525
		this.supportedCategoricalEnumerations.add(supportedCategoricalEnumeration);
526
	}
527
	/**
528
	 * Removes one element from the set of {@link #getSupportedCategoricalEnumerations() supported state vocabularies}
529
	 * assigned to <i>this</i> feature.
530
	 *
531
	 * @param  supportedCategoricalEnumeration	the term vocabulary which should be removed
532
	 * @see     								#getSupportedCategoricalEnumerations()
533
	 * @see     								#addSupportedCategoricalEnumeration(TermVocabulary)
534
	 */
535
	public void removeSupportedCategoricalEnumeration(
536
			TermVocabulary<State> supportedCategoricalEnumeration) {
537
		this.supportedCategoricalEnumerations.remove(supportedCategoricalEnumeration);
538
	}
539

    
540
	@XmlElement(name = "KindOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
541
    @XmlIDREF
542
    @XmlSchemaType(name = "IDREF")
543
    @Override
544
	public Feature getKindOf(){
545
		return super.getKindOf();
546
	}
547

    
548
	@Override
549
    public void setKindOf(Feature kindOf){
550
		super.setKindOf(kindOf);
551
	}
552

    
553
	@Override
554
    @XmlElement(name = "PartOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
555
	@XmlIDREF
556
    @XmlSchemaType(name = "IDREF")
557
	public Feature getPartOf(){
558
		return super.getPartOf();
559
	}
560

    
561
	@Override
562
    public void setPartOf(Feature partOf){
563
		super.setPartOf(partOf);
564
	}
565

    
566
	@Override
567
    @XmlElementWrapper(name = "Generalizations", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
568
	@XmlElement(name = "GeneralizationOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
569
    @XmlIDREF
570
    @XmlSchemaType(name = "IDREF")
571
	public Set<Feature> getGeneralizationOf(){
572
		return super.getGeneralizationOf();
573
	}
574

    
575
	@Override
576
    protected void setGeneralizationOf(Set<Feature> value){
577
		super.setGeneralizationOf(value);
578
	}
579

    
580
	@Override
581
    @XmlElementWrapper(name = "Includes", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
582
	@XmlElement(name = "Include", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
583
	@XmlIDREF
584
    @XmlSchemaType(name = "IDREF")
585
	public Set<Feature> getIncludes(){
586
		return super.getIncludes();
587
	}
588

    
589
	@Override
590
    protected void setIncludes(Set<Feature> includes) {
591
		super.setIncludes(includes);
592
	}
593

    
594
// ***************** Invers Label *****************************************/
595

    
596
	public Set<Representation> getInverseRepresentations() {
597
        return inverseRepresentations;
598
    }
599
    public void addInverseRepresentation(Representation inverseRepresentation) {
600
        this.inverseRepresentations.add(inverseRepresentation);
601
    }
602
    public void removeInverseRepresentation(Representation inverseRepresentation) {
603
        this.inverseRepresentations.remove(inverseRepresentation);
604
    }
605
    /*
606
     * Inverse representation convenience methods similar to TermBase.xxx
607
     * @see eu.etaxonomy.cdm.model.common.TermBase#getLabel()
608
     */
609
    @Transient
610
    public String getInverseLabel() {
611
        if(getInverseLabel(Language.DEFAULT()) != null){
612
            return this.getInverseRepresentation(Language.DEFAULT()).getLabel();
613
        }else{
614
            for (Representation r : inverseRepresentations){
615
                return r.getLabel();
616
            }
617
        }
618
        return super.getUuid().toString();
619
    }
620
    public String getInverseLabel(Language lang) {
621
        Representation r = this.getInverseRepresentation(lang);
622
        if(r==null){
623
            return null;
624
        }else{
625
            return r.getLabel();
626
        }
627
    }
628
    public Representation getInverseRepresentation(Language lang) {
629
        Representation result = null;
630
        for (Representation repr : this.getInverseRepresentations()){
631
            if (lang.equals(repr.getLanguage())){
632
                result = repr;
633
            }
634
        }
635
        return result;
636
    }
637
// ****************** END INVERS REPRESENTATION **************************/
638

    
639
	/**
640
	 * Creates and returns a new feature instance on the basis of a given string
641
	 * list (containing an UUID, an URI, a label and a description) and a given
642
	 * {@link Language language} to be associated with the description. Furthermore
643
	 * the flags concerning the supported subclasses of {@link DescriptionElementBase description elements}
644
	 * are set according to a particular string belonging to the given
645
	 * string list.<BR>
646
	 * This method overrides the readCsvLine method from {@link DefinedTermBase#readCsvLine(List, Language) DefinedTermBase}.
647
	 *
648
	 * @param  csvLine	the string list with elementary information for attributes
649
	 * @param  lang		the language in which the description has been formulated
650
	 * @see     		#NewInstance(String, String, String)
651
	 */
652
	@Override
653
	public Feature readCsvLine(Class<Feature> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
654
		Feature newInstance = super.readCsvLine(termClass, csvLine, terms, abbrevAsId);
655
		String text = csvLine.get(4);
656
		if (text != null && text.length() >= 6){
657
			if ("1".equals(text.substring(0, 1))){newInstance.setSupportsTextData(true);};
658
			if ("1".equals(text.substring(1, 2))){newInstance.setSupportsQuantitativeData(true);};
659
			if ("1".equals(text.substring(2, 3))){newInstance.setSupportsDistribution(true);};
660
			if ("1".equals(text.substring(3, 4))){newInstance.setSupportsIndividualAssociation(true);};
661
			if ("1".equals(text.substring(4, 5))){newInstance.setSupportsTaxonInteraction(true);};
662
			if ("1".equals(text.substring(5, 6))){newInstance.setSupportsCommonTaxonName(true);};
663
			// if ("1".equals(text.substring(6, 7))){newInstance.setSupportsCategoricalData(true);};
664
			//there is no abbreviated label for features yet, if there is one in future we need to increment the index for supportXXX form 4 to 5
665
			newInstance.getRepresentation(Language.DEFAULT()).setAbbreviatedLabel(null);
666
		}
667
		return newInstance;
668
	}
669

    
670
//******************************* STATIC METHODS *****************************************
671

    
672
	protected static Feature getTermByUuid(UUID uuid){
673
	    if (termMap == null || termMap.isEmpty()){
674
            return getTermByClassAndUUID(Feature.class, uuid);
675
        } else {
676
			return termMap.get(uuid);
677
        }
678
	}
679

    
680
	/**
681
	 * Returns the "unknown" feature. This feature allows to store values of
682
	 * {@link DescriptionElementBase description elements} even if it is momentarily
683
	 * not known what they mean.
684
	 */
685
	public static final Feature UNKNOWN(){
686
		return getTermByUuid(uuidUnknown);
687
	}
688

    
689
	/**
690
	 * Returns the "description" feature. This feature allows to handle global
691
	 * {@link DescriptionElementBase description elements} for a global {@link DescriptionBase description}.<BR>
692
	 * The "description" feature is the highest level feature.
693
	 */
694
	public static final Feature DESCRIPTION(){
695
		return getTermByUuid(uuidDescription);
696
	}
697

    
698
	/**
699
	 * Returns the "distribution" feature. This feature allows to handle only
700
	 * {@link Distribution distributions}.
701
	 *
702
	 * @see	#isSupportsDistribution()
703
	 */
704
	public static final Feature DISTRIBUTION(){
705
		return getTermByUuid(uuidDistribution);
706
	}
707

    
708
	/**
709
	 * Returns the "discussion" feature. This feature can only be described
710
	 * with {@link TextData text data}.
711
	 *
712
	 * @see	#isSupportsTextData()
713
	 */
714
	public static final Feature DISCUSSION(){
715
		return getTermByUuid(uuidDiscussion);
716
	}
717

    
718
	/**
719
	 * Returns the "ecology" feature. This feature only applies
720
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
721
	 * The "ecology" feature generalizes all other possible features concerning
722
	 * ecological matters.
723
	 */
724
	public static final Feature ECOLOGY(){
725
		return getTermByUuid(uuidEcology);
726
	}
727

    
728
	/**
729
	 * Returns the "habitat" feature. This feature only applies
730
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
731
	 * The "habitat" feature generalizes all other possible features concerning
732
	 * habitat matters.
733
	 */
734
	public static final Feature HABITAT(){
735
		return getTermByUuid(uuidHabitat);
736
	}
737

    
738

    
739
	/**
740
	 * Returns the "habitat & ecology" feature. This feature only applies
741
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
742
	 * The "habitat & ecology" feature generalizes all other possible features concerning
743
	 * habitat and ecology matters.
744
	 */
745
	public static final Feature HABITAT_ECOLOGY(){
746
		return getTermByUuid(uuidHabitatAndEcology);
747
	}
748

    
749
	/**
750
	 * Returns the "biology_ecology" feature. This feature only applies
751
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
752
	 * The "biology_ecology" feature generalizes all possible features concerning
753
	 * biological aspects of ecological matters.
754
	 *
755
	 * @see #ECOLOGY()
756
	 */
757
	public static final Feature BIOLOGY_ECOLOGY(){
758
		return getTermByUuid(uuidBiologyEcology);
759
	}
760

    
761
	/**
762
	 * Returns the "chromosome number" feature. This feature only applies
763
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
764
	 */
765
	public static final Feature CHROMOSOME_NUMBER(){
766
		return getTermByUuid(uuidChromosomeNumber);
767
	}
768

    
769

    
770
	/**
771
	 * Returns the "key" feature. This feature is the "upper" feature generalizing
772
	 * all features being used within an identification key.
773
	 */
774
	public static final Feature KEY(){
775
		return getTermByUuid(uuidKey);
776
	}
777

    
778

    
779
	/**
780
	 * Returns the "materials_examined" feature. This feature can only be described
781
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
782
	 * mentioning which material has been examined in order to accomplish
783
	 * the description. This feature applies only to
784
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
785
	 */
786
	public static final Feature MATERIALS_EXAMINED(){
787
		return getTermByUuid(uuidMaterialsExamined);
788
	}
789

    
790
	/**
791
	 * Returns the "materials_methods" feature. This feature can only be described
792
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
793
	 * mentioning which methods have been adopted to analyze the material in
794
	 * order to accomplish the description. This feature applies only to
795
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
796
	 */
797
	public static final Feature MATERIALS_METHODS(){
798
		return getTermByUuid(uuidMaterialsMethods);
799
	}
800

    
801
	/**
802
	 * Returns the "etymology" feature. This feature can only be described
803
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
804
	 * giving some information about the history of the taxon name. This feature applies only to
805
	 * {@link TaxonNameDescription taxon name descriptions}.
806
	 */
807
	public static final Feature ETYMOLOGY(){
808
		return getTermByUuid(uuidEtymology);
809
	}
810

    
811
	/**
812
	 * Returns the "diagnosis" feature. This feature can only be described
813
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}.
814
	 * This feature applies only to {@link SpecimenDescription specimen descriptions} or to
815
	 * {@link TaxonDescription taxon descriptions}.
816
	 */
817
	public static final Feature DIAGNOSIS(){
818
		return getTermByUuid(uuidDiagnosis);
819
	}
820

    
821

    
822
	/**
823
	 * Returns the "introduction" feature. This feature can only be described
824
	 * with {@link TextData text data}.
825
	 *
826
	 * @see	#isSupportsTextData()
827
	 */
828
	public static final Feature INTRODUCTION(){
829
		return getTermByUuid(uuidIntroduction);
830
	}
831

    
832
	/**
833
	 * Returns the "protologue" feature. This feature can only be described
834
	 * with {@link TextData text data} reproducing the content of the protologue
835
	 * (or some information about it) of the taxon name. This feature applies only to
836
	 * {@link TaxonNameDescription taxon name descriptions}.
837
	 *
838
	 * @see	#isSupportsTextData()
839
	 */
840
	public static final Feature PROTOLOGUE(){
841
		return getTermByUuid(uuidProtologue);
842
	}
843

    
844
	/**
845
	 * Returns the "common_name" feature. This feature allows to handle only
846
	 * {@link CommonTaxonName common names}.
847
	 *
848
	 * @see	#isSupportsCommonTaxonName()
849
	 */
850
	public static final Feature COMMON_NAME(){
851
		return getTermByUuid(uuidCommonName);
852
	}
853

    
854
	/**
855
	 * Returns the "phenology" feature. This feature can only be described
856
	 * with {@link CategoricalData categorical data} or eventually with {@link TextData text data}
857
	 * containing information time about recurring natural phenomena.
858
	 * This feature only applies to {@link TaxonDescription taxon descriptions}.<BR>
859
	 * The "phenology" feature generalizes all other possible features
860
	 * concerning time information about particular natural phenomena
861
	 * (such as "first flight of butterflies").
862
	 */
863
	public static final Feature PHENOLOGY(){
864
		return getTermByUuid(uuidPhenology);
865
	}
866

    
867
	/**
868
	 * Returns the "occurrence" feature.
869
	 */
870
	public static final Feature OCCURRENCE(){
871
		return getTermByUuid(uuidOccurrence);
872
	}
873

    
874
	/**
875
	 * Returns the "anatomy" feature.
876
	 */
877
	public static final Feature ANATOMY(){
878
		return getTermByUuid(uuidAnatomy);
879
	}
880
	/**
881
	 * Returns the "hostplant" feature.
882
	 */
883
	public static final Feature HOSTPLANT(){
884
		return getTermByUuid(uuidHostPlant);
885
	}
886
	/**
887
	 * Returns the "pathogen agent" feature.
888
	 */
889
	public static final Feature PATHOGEN_AGENT(){
890
		return getTermByUuid(uuidPathogenAgent);
891
	}
892

    
893
	/**
894
	 * Returns the "citation" feature. This feature can only be described
895
	 * with {@link TextData text data}.
896
	 *
897
	 * @see	#isSupportsTextData()
898
	 */
899
	public static final Feature CITATION(){
900
		return getTermByUuid(uuidCitation);
901
	}
902

    
903
	/**
904
	 * Returns the "additional_publication" feature. This feature can only be
905
	 * described with {@link TextData text data} with information about a
906
	 * publication where a {@link TaxonNameBase taxon name} has also been published
907
	 * but which is not the {@link TaxonNameBase#getNomenclaturalReference() nomenclatural reference}.
908
	 * This feature applies only to {@link TaxonNameDescription taxon name descriptions}.
909
	 *
910
	 * @see	#isSupportsTextData()
911
	 */
912
	public static final Feature ADDITIONAL_PUBLICATION(){
913
		return getTermByUuid(uuidAdditionalPublication);
914
	}
915

    
916

    
917
	/**
918
	 * Returns the "uses" feature. This feature only applies
919
	 * to {@link TaxonDescription taxon descriptions}.<BR>
920
	 * The "uses" feature generalizes all other possible features concerning
921
	 * particular uses (for instance "industrial use of seeds").
922
	 */
923
	public static final Feature USES(){
924
		return getTermByUuid(uuidUses);
925
	}
926

    
927
	public static final Feature USERECORD(){
928
		return getTermByUuid(uuidUseRecord);
929
	}
930

    
931

    
932
	/**
933
	 * Returns the "conservation" feature. This feature only applies
934
	 * to {@link SpecimenDescription specimen descriptions} and generalizes
935
	 * methods and conditions for the conservation of {@link Specimen specimens}.<BR>
936
	 */
937
	public static final Feature CONSERVATION(){
938
		return getTermByUuid(uuidConservation);
939
	}
940

    
941

    
942
	/**
943
	 * Returns the "cultivation" feature.
944
	 */
945
	public static final Feature CULTIVATION(){
946
		return getTermByUuid(uuidCultivation);
947
	}
948

    
949

    
950
	/**
951
	 * Returns the "image" feature.
952
	 */
953
	public static final Feature IMAGE(){
954
		return getTermByUuid(uuidImage);
955
	}
956

    
957
	/**
958
	 * Returns the "individuals association" feature.
959
	 */
960
	public static final Feature INDIVIDUALS_ASSOCIATION(){
961
		Feature individuals_association =  getTermByUuid(uuidIndividualsAssociation);
962
		Set<Feature> generalizationOf = new HashSet<Feature>();
963
		generalizationOf.add(SPECIMEN());
964
		generalizationOf.add(OBSERVATION());
965
		individuals_association.setGeneralizationOf(generalizationOf);
966
		return individuals_association;
967

    
968
	}
969

    
970
	public static final Feature SPECIMEN(){
971
		return getTermByUuid(uuidSpecimen);
972
	}
973

    
974
	public static final Feature OBSERVATION(){
975
		return getTermByUuid(uuidObservation);
976
	}
977

    
978
	/**
979
	 * The status of a taxon. Usually the status should be determined within a {@link Distribution distribution}.
980
	 * If this is not possible for some reason (e.g. the area is not well defined) the status feature
981
	 * may be used.
982
	 * @return
983
	 */
984
	public static final Feature STATUS(){
985
		return getTermByUuid(uuidStatus);
986
	}
987

    
988
	public static final Feature SYSTEMATICS(){
989
		return getTermByUuid(uuidSystematics);
990
	}
991

    
992
	/**
993
	 * Returns the "hybrid_parent" feature. This feature can only be used
994
	 * by {@link TaxonInteraction taxon interactions}.<BR>
995
	 * <P>
996
	 * Note: It must be distinguished between hybrid relationships as
997
	 * relevant nomenclatural relationships between {@link BotanicalName plant names}
998
	 * on the one side and the biological relation between two {@link Taxon taxa}
999
	 * as it is here the case on the other one.
1000
	 *
1001
	 * @see	#isSupportsTaxonInteraction()
1002
	 * @see	HybridRelationshipType
1003
	 */
1004
	public static final Feature HYBRID_PARENT(){
1005
		//TODO
1006
		logger.warn("HYBRID_PARENT not yet implemented");
1007
		return null;
1008
	}
1009

    
1010
	@Override
1011
	protected void setDefaultTerms(TermVocabulary<Feature> termVocabulary) {
1012
		if (termMap == null){  //needed because there are multiple feature vocabularies
1013
			termMap = new HashMap<UUID, Feature>();
1014
		}
1015
		for (Feature term : termVocabulary.getTerms()){
1016
			termMap.put(term.getUuid(), term);
1017
		}
1018
	}
1019

    
1020
//*********************************** CLONE *********************************************************/
1021

    
1022
    @Override
1023
    public Object clone() {
1024
        Feature result = (Feature)super.clone();
1025

    
1026
        result.inverseRepresentations = new HashSet<Representation>();
1027
        for (Representation rep: this.inverseRepresentations){
1028
            result.addInverseRepresentation((Representation)rep.clone());
1029
        }
1030

    
1031
        //no changes to: symmetric, transitiv
1032
        return result;
1033
    }
1034

    
1035
}
(8-8/36)