Project

General

Profile

Download (35.6 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.JoinTable;
23
import javax.persistence.ManyToMany;
24
import javax.persistence.OneToMany;
25
import javax.xml.bind.annotation.XmlAccessType;
26
import javax.xml.bind.annotation.XmlAccessorType;
27
import javax.xml.bind.annotation.XmlElement;
28
import javax.xml.bind.annotation.XmlElementWrapper;
29
import javax.xml.bind.annotation.XmlIDREF;
30
import javax.xml.bind.annotation.XmlRootElement;
31
import javax.xml.bind.annotation.XmlSchemaType;
32
import javax.xml.bind.annotation.XmlType;
33

    
34
import org.apache.log4j.Logger;
35
import org.hibernate.envers.Audited;
36
import org.hibernate.search.annotations.Indexed;
37

    
38
import eu.etaxonomy.cdm.model.common.DefinedTerm;
39
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.common.TermType;
42
import eu.etaxonomy.cdm.model.common.TermVocabulary;
43
import eu.etaxonomy.cdm.model.name.BotanicalName;
44
import eu.etaxonomy.cdm.model.name.HybridRelationshipType;
45
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
46
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
47
import eu.etaxonomy.cdm.model.taxon.Taxon;
48

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

    
103
	protected static Map<UUID, Feature> termMap = null;
104

    
105
	private boolean supportsTextData = true;   //by default text data should be always supported
106

    
107
	private boolean supportsQuantitativeData;
108

    
109
	private boolean supportsDistribution;
110

    
111
	private boolean supportsIndividualAssociation;
112

    
113
	private boolean supportsTaxonInteraction;
114

    
115
	private boolean supportsCategoricalData;
116

    
117
	private boolean supportsCommonTaxonName;
118

    
119
	/*
120
	 * FIXME Should this be Many-To-Many or do we expect each Feature to have its own unique modifier enums?
121
	 */
122
	@OneToMany(fetch = FetchType.LAZY)
123
    @JoinTable(name="DefinedTermBase_RecommendedModifierEnumeration")
124
	private final Set<TermVocabulary<DefinedTerm>> recommendedModifierEnumeration = new HashSet<TermVocabulary<DefinedTerm>>();
125

    
126

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

    
131
	/*
132
	 * FIXME Should this be Many-To-Many or do we expect each Feature to have its own unique state enums?
133
	 */
134
	@OneToMany(fetch = FetchType.LAZY)
135
    @JoinTable(name="DefinedTermBase_SupportedCategoricalEnumeration")
136
	private final Set<TermVocabulary<State>> supportedCategoricalEnumerations = new HashSet<TermVocabulary<State>>();
137

    
138

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

    
143
/* ***************** CONSTRUCTOR AND FACTORY METHODS **********************************/
144

    
145
	//for hibernate use only
146
	@Deprecated
147
	protected Feature() {
148
		super(TermType.Feature);
149
	}
150

    
151
	/**
152
	 * Class constructor: creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
153
	 * a label and a label abbreviation.
154
	 *
155
	 * @param	term  		 the string (in the default language) describing the
156
	 * 						 new feature to be created
157
	 * @param	label  		 the string identifying the new feature to be created
158
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
159
	 * 						 new feature to be created
160
	 * @see 				 #Feature()
161
	 */
162
	protected Feature(String term, String label, String labelAbbrev) {
163
		super(TermType.Feature, term, label, labelAbbrev);
164
	}
165

    
166
	/**
167
	 * Creates a new empty feature instance.
168
	 *
169
	 * @see #NewInstance(String, String, String)
170
	 */
171
	public static Feature NewInstance() {
172
		return new Feature();
173
	}
174

    
175
	/**
176
	 * Creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
177
	 * a label and a label abbreviation.
178
	 *
179
	 * @param	term  		 the string (in the default language) describing the
180
	 * 						 new feature to be created
181
	 * @param	label  		 the string identifying the new feature to be created
182
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
183
	 * 						 new feature to be created
184
	 * @see 				 #readCsvLine(List, Language)
185
	 * @see 				 #NewInstance()
186
	 */
187
	public static Feature NewInstance(String term, String label, String labelAbbrev){
188
		return new Feature(term, label, labelAbbrev);
189
	}
190

    
191
/* *************************************************************************************/
192

    
193

    
194
	/* (non-Javadoc)
195
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#resetTerms()
196
	 */
197
	@Override
198
	public void resetTerms(){
199
		termMap = null;
200
	}
201

    
202

    
203
	/**
204
	 * Returns the boolean value of the flag indicating whether <i>this</i>
205
	 * feature can be described with {@link QuantitativeData quantitative data} (true)
206
	 * or not (false). If this flag is set <i>this</i> feature can only apply to
207
	 * {@link TaxonDescription taxon descriptions} or {@link SpecimenDescription specimen descriptions}.
208
	 *
209
	 * @return  the boolean value of the supportsQuantitativeData flag
210
	 */
211
	@XmlElement(name = "SupportsQuantitativeData")
212
	public boolean isSupportsQuantitativeData() {
213
		return supportsQuantitativeData;
214
	}
215

    
216
	/**
217
	 * @see	#isSupportsQuantitativeData()
218
	 */
219
	public void setSupportsQuantitativeData(boolean supportsQuantitativeData) {
220
		this.supportsQuantitativeData = supportsQuantitativeData;
221
	}
222

    
223
	/**
224
	 * Returns the boolean value of the flag indicating whether <i>this</i>
225
	 * feature can be described with {@link TextData text data} (true)
226
	 * or not (false).
227
	 *
228
	 * @return  the boolean value of the supportsTextData flag
229
	 */
230
	@XmlElement(name = "SupportsTextData")
231
	public boolean isSupportsTextData() {
232
		return supportsTextData;
233
	}
234

    
235
	/**
236
	 * @see	#isSupportsTextData()
237
	 */
238
	public void setSupportsTextData(boolean supportsTextData) {
239
		this.supportsTextData = supportsTextData;
240
	}
241

    
242
	/**
243
	 * Returns the boolean value of the flag indicating whether <i>this</i>
244
	 * feature can be described with {@link Distribution distribution} objects
245
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
246
	 * is the {@link #DISTRIBUTION() distribution feature}.
247
	 *
248
	 * @return  the boolean value of the supportsDistribution flag
249
	 */
250
	@XmlElement(name = "SupportsDistribution")
251
	public boolean isSupportsDistribution() {
252
		return supportsDistribution;
253
	}
254

    
255
	/**
256
	 * @see	#isSupportsDistribution()
257
	 */
258
	public void setSupportsDistribution(boolean supportsDistribution) {
259
		this.supportsDistribution = supportsDistribution;
260
	}
261

    
262
	/**
263
	 * Returns the boolean value of the flag indicating whether <i>this</i>
264
	 * feature can be described with {@link IndividualsAssociation individuals associations}
265
	 * (true) or not (false).
266
	 *
267
	 * @return  the boolean value of the supportsIndividualAssociation flag
268
	 */
269
	@XmlElement(name = "SupportsIndividualAssociation")
270
	public boolean isSupportsIndividualAssociation() {
271
		return supportsIndividualAssociation;
272
	}
273

    
274
	/**
275
	 * @see	#isSupportsIndividualAssociation()
276
	 */
277
	public void setSupportsIndividualAssociation(
278
			boolean supportsIndividualAssociation) {
279
		this.supportsIndividualAssociation = supportsIndividualAssociation;
280
	}
281

    
282
	/**
283
	 * Returns the boolean value of the flag indicating whether <i>this</i>
284
	 * feature can be described with {@link TaxonInteraction taxon interactions}
285
	 * (true) or not (false).
286
	 *
287
	 * @return  the boolean value of the supportsTaxonInteraction flag
288
	 */
289
	@XmlElement(name = "SupportsTaxonInteraction")
290
	public boolean isSupportsTaxonInteraction() {
291
		return supportsTaxonInteraction;
292
	}
293

    
294
	/**
295
	 * @see	#isSupportsTaxonInteraction()
296
	 */
297
	public void setSupportsTaxonInteraction(boolean supportsTaxonInteraction) {
298
		this.supportsTaxonInteraction = supportsTaxonInteraction;
299
	}
300

    
301
	/**
302
	 * Returns the boolean value of the flag indicating whether <i>this</i>
303
	 * feature can be described with {@link CommonTaxonName common names}
304
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
305
	 * is the {@link #COMMON_NAME() common name feature}.
306
	 *
307
	 * @return  the boolean value of the supportsCommonTaxonName flag
308
	 */
309
	@XmlElement(name = "SupportsCommonTaxonName")
310
	public boolean isSupportsCommonTaxonName() {
311
		return supportsCommonTaxonName;
312
	}
313

    
314
	/**
315
	 * @see	#isSupportsTaxonInteraction()
316
	 */
317
	public void setSupportsCommonTaxonName(boolean supportsCommonTaxonName) {
318
		this.supportsCommonTaxonName = supportsCommonTaxonName;
319
	}
320

    
321
	/**
322
	 * Returns the boolean value of the flag indicating whether <i>this</i>
323
	 * feature can be described with {@link CategoricalData categorical data}
324
	 * (true) or not (false).
325
	 *
326
	 * @return  the boolean value of the supportsCategoricalData flag
327
	 */
328
	@XmlElement(name = "SupportsCategoricalData")
329
	public boolean isSupportsCategoricalData() {
330
		return supportsCategoricalData;
331
	}
332

    
333
	/**
334
	 * @see	#supportsCategoricalData()
335
	 */
336
	public void setSupportsCategoricalData(boolean supportsCategoricalData) {
337
		this.supportsCategoricalData = supportsCategoricalData;
338
	}
339

    
340

    
341
	/**
342
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the
343
	 * {@link Modifier modifiers} recommended to be used for {@link DescriptionElementBase description elements}
344
	 * with <i>this</i> feature.
345
	 *
346
	 */
347
	@XmlElementWrapper(name = "RecommendedModifierEnumerations")
348
	@XmlElement(name = "RecommendedModifierEnumeration")
349
	@XmlIDREF
350
	@XmlSchemaType(name = "IDREF")
351
	public Set<TermVocabulary<DefinedTerm>> getRecommendedModifierEnumeration() {
352
		return recommendedModifierEnumeration;
353
	}
354

    
355
	/**
356
	 * Adds a {@link TermVocabulary term vocabulary} (with {@link Modifier modifiers}) to the set of
357
	 * {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies} assigned
358
	 * to <i>this</i> feature.
359
	 *
360
	 * @param recommendedModifierEnumeration	the term vocabulary to be added
361
	 * @see    	   								#getRecommendedModifierEnumeration()
362
	 */
363
	public void addRecommendedModifierEnumeration(
364
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
365
		this.recommendedModifierEnumeration.add(recommendedModifierEnumeration);
366
	}
367
	/**
368
	 * Removes one element from the set of {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies}
369
	 * assigned to <i>this</i> feature.
370
	 *
371
	 * @param  recommendedModifierEnumeration	the term vocabulary which should be removed
372
	 * @see     								#getRecommendedModifierEnumeration()
373
	 * @see     								#addRecommendedModifierEnumeration(TermVocabulary)
374
	 */
375
	public void removeRecommendedModifierEnumeration(
376
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
377
		this.recommendedModifierEnumeration.remove(recommendedModifierEnumeration);
378
	}
379

    
380
	/**
381
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
382
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
383
	 */
384
	@XmlElementWrapper(name = "RecommendedStatisticalMeasures")
385
	@XmlElement(name = "RecommendedStatisticalMeasure")
386
	@XmlIDREF
387
	@XmlSchemaType(name = "IDREF")
388
	public Set<StatisticalMeasure> getRecommendedStatisticalMeasures() {
389
		return recommendedStatisticalMeasures;
390
	}
391

    
392
	/**
393
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
394
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
395
	 * to <i>this</i> feature.
396
	 *
397
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
398
	 * @see    	   							#getRecommendedStatisticalMeasures()
399
	 */
400
	public void addRecommendedStatisticalMeasure(
401
			StatisticalMeasure recommendedStatisticalMeasure) {
402
		this.recommendedStatisticalMeasures.add(recommendedStatisticalMeasure);
403
	}
404
	/**
405
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
406
	 * assigned to <i>this</i> feature.
407
	 *
408
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
409
	 * @see     								#getRecommendedStatisticalMeasures()
410
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
411
	 */
412
	public void removeRecommendedStatisticalMeasure(
413
			StatisticalMeasure recommendedStatisticalMeasure) {
414
		this.recommendedStatisticalMeasures.remove(recommendedStatisticalMeasure);
415
	}
416

    
417
	/**
418
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
419
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
420
	 */
421
	@XmlElementWrapper(name = "RecommendedMeasurementUnits")
422
	@XmlElement(name = "RecommendedMeasurementUnit")
423
	@XmlIDREF
424
	@XmlSchemaType(name = "IDREF")
425
	public Set<MeasurementUnit> getRecommendedMeasurementUnits() {
426
		return recommendedMeasurementUnits;
427
	}
428

    
429
	/**
430
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
431
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
432
	 * to <i>this</i> feature.
433
	 *
434
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
435
	 * @see    	   							#getRecommendedStatisticalMeasures()
436
	 */
437
	public void addRecommendedMeasurementUnit(
438
			MeasurementUnit recommendedMeasurementUnit) {
439
		this.recommendedMeasurementUnits.add(recommendedMeasurementUnit);
440
	}
441
	/**
442
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
443
	 * assigned to <i>this</i> feature.
444
	 *
445
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
446
	 * @see     								#getRecommendedStatisticalMeasures()
447
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
448
	 */
449
	public void removeRecommendedMeasurementUnit(
450
			MeasurementUnit recommendedMeasurementUnit) {
451
		this.recommendedMeasurementUnits.remove(recommendedMeasurementUnit);
452
	}
453

    
454
	/**
455
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the list of
456
	 * possible {@link State states} to be used in {@link CategoricalData categorical data}
457
	 * with <i>this</i> feature.
458
	 *
459
	 */
460
	@XmlElementWrapper(name = "SupportedCategoricalEnumerations")
461
	@XmlElement(name = "SupportedCategoricalEnumeration")
462
	@XmlIDREF
463
	@XmlSchemaType(name = "IDREF")
464
	public Set<TermVocabulary<State>> getSupportedCategoricalEnumerations() {
465
		return supportedCategoricalEnumerations;
466
	}
467

    
468
	/**
469
	 * Adds a {@link TermVocabulary term vocabulary} to the set of
470
	 * {@link #getSupportedCategoricalEnumerations() supported state vocabularies} assigned
471
	 * to <i>this</i> feature.
472
	 *
473
	 * @param supportedCategoricalEnumeration	the term vocabulary which should be removed
474
	 * @see    	   								#getSupportedCategoricalEnumerations()
475
	 */
476
	public void addSupportedCategoricalEnumeration(
477
			TermVocabulary<State> supportedCategoricalEnumeration) {
478
		this.supportedCategoricalEnumerations.add(supportedCategoricalEnumeration);
479
	}
480
	/**
481
	 * Removes one element from the set of {@link #getSupportedCategoricalEnumerations() supported state vocabularies}
482
	 * assigned to <i>this</i> feature.
483
	 *
484
	 * @param  supportedCategoricalEnumeration	the term vocabulary which should be removed
485
	 * @see     								#getSupportedCategoricalEnumerations()
486
	 * @see     								#addSupportedCategoricalEnumeration(TermVocabulary)
487
	 */
488
	public void removeSupportedCategoricalEnumeration(
489
			TermVocabulary<State> supportedCategoricalEnumeration) {
490
		this.supportedCategoricalEnumerations.remove(supportedCategoricalEnumeration);
491
	}
492

    
493
	@XmlElement(name = "KindOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
494
    @XmlIDREF
495
    @XmlSchemaType(name = "IDREF")
496
    @Override
497
	public Feature getKindOf(){
498
		return super.getKindOf();
499
	}
500

    
501
	@Override
502
    public void setKindOf(Feature kindOf){
503
		super.setKindOf(kindOf);
504
	}
505

    
506
	@Override
507
    @XmlElement(name = "PartOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
508
	@XmlIDREF
509
    @XmlSchemaType(name = "IDREF")
510
	public Feature getPartOf(){
511
		return super.getPartOf();
512
	}
513

    
514
	@Override
515
    public void setPartOf(Feature partOf){
516
		super.setPartOf(partOf);
517
	}
518

    
519
	@Override
520
    @XmlElementWrapper(name = "Generalizations", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
521
	@XmlElement(name = "GeneralizationOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
522
    @XmlIDREF
523
    @XmlSchemaType(name = "IDREF")
524
	public Set<Feature> getGeneralizationOf(){
525
		return super.getGeneralizationOf();
526
	}
527

    
528
	@Override
529
    protected void setGeneralizationOf(Set<Feature> value){
530
		super.setGeneralizationOf(value);
531
	}
532

    
533
	@Override
534
    @XmlElementWrapper(name = "Includes", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
535
	@XmlElement(name = "Include", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
536
	@XmlIDREF
537
    @XmlSchemaType(name = "IDREF")
538
	public Set<Feature> getIncludes(){
539
		return super.getIncludes();
540
	}
541

    
542
	@Override
543
    protected void setIncludes(Set<Feature> includes) {
544
		super.setIncludes(includes);
545
	}
546

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

    
555
	private static final UUID uuidBiologyEcology = UUID.fromString("9832e24f-b670-43b4-ac7c-20a7261a1d8c");
556
	private static final UUID uuidKey = UUID.fromString("a677f827-22b9-4205-bb37-11cb48dd9106");
557
	private static final UUID uuidMaterialsExamined = UUID.fromString("7c0c7571-a864-47c1-891d-01f59000dae1");
558
	private static final UUID uuidMaterialsMethods = UUID.fromString("1e87d9c3-0844-4a03-9686-773e2ccb3ab6");
559
	private static final UUID uuidEtymology = UUID.fromString("dd653d48-355c-4aec-a4e7-724f6eb29f8d");
560
	private static final UUID uuidDiagnosis = UUID.fromString("d43d8501-ceab-4caa-9e51-e87138528fac");
561
	private static final UUID uuidProtologue = UUID.fromString("71b356c5-1e3f-4f5d-9b0f-c2cf8ae7779f");
562
	private static final UUID uuidCommonName = UUID.fromString("fc810911-51f0-4a46-ab97-6562fe263ae5");
563
	private static final UUID uuidPhenology = UUID.fromString("a7786d3e-7c58-4141-8416-346d4c80c4a2");
564
	private static final UUID uuidOccurrence = UUID.fromString("5deff505-1a32-4817-9a74-50e6936fd630");
565
	private static final UUID uuidCitation = UUID.fromString("99b2842f-9aa7-42fa-bd5f-7285311e0101");
566
	private static final UUID uuidAdditionalPublication = UUID.fromString("2c355c16-cb04-4858-92bf-8da8d56dea95");
567
	private static final UUID uuidUses = UUID.fromString("e5374d39-b210-47c7-bec1-bee05b5f1cb6");
568
	private static final UUID uuidConservation = UUID.fromString("4518fc20-2492-47de-b345-777d2b83c9cf");
569
	private static final UUID uuidCultivation = UUID.fromString("e28965b2-a367-48c5-b954-8afc8ac2c69b");
570
	private static final UUID uuidIntroduction = UUID.fromString("e75255ca-8ff4-4905-baad-f842927fe1d3");
571
	private static final UUID uuidDiscussion = UUID.fromString("d3c4cbb6-0025-4322-886b-cd0156753a25");
572
	private static final UUID uuidImage = UUID.fromString("84193b2c-327f-4cce-90ef-c8da18fd5bb5");
573
	private static final UUID uuidAnatomy = UUID.fromString("94213b2c-e67a-4d37-25ef-e8d316edfba1");
574
	private static final UUID uuidHostPlant = UUID.fromString("6e9de1d5-05f0-40d5-8786-2fe30d0d894d");
575
	private static final UUID uuidPathogenAgent = UUID.fromString("002d05f2-fd72-49f1-ba4d-196cf09240b5");
576
	private static final UUID uuidIndividualsAssociation = UUID.fromString("e2308f37-ddc5-447d-b483-5e2171dd85fd");
577
	private static final UUID uuidSpecimen = UUID.fromString("8200e050-d5fd-4cac-8a76-4b47afb13809");
578
	private static final UUID uuidObservation = UUID.fromString("f59e747d-0b4f-4bf7-b69a-cbd50bc78595");
579
	private static final UUID uuidStatus = UUID.fromString("86d40635-2a63-4ad6-be75-9faa4a6a57fb");
580
	private static final UUID uuidSystematics = UUID.fromString("bd9aca17-cd0e-4418-a3a1-1a4b80dbc162");
581
	private static final UUID uuidUseRecord = UUID.fromString("8125a59d-b4d5-4485-89ea-67306297b599");
582

    
583
	/**
584
	 * Creates and returns a new feature instance on the basis of a given string
585
	 * list (containing an UUID, an URI, a label and a description) and a given
586
	 * {@link Language language} to be associated with the description. Furthermore
587
	 * the flags concerning the supported subclasses of {@link DescriptionElementBase description elements}
588
	 * are set according to a particular string belonging to the given
589
	 * string list.<BR>
590
	 * This method overrides the readCsvLine method from {@link DefinedTermBase#readCsvLine(List, Language) DefinedTermBase}.
591
	 *
592
	 * @param  csvLine	the string list with elementary information for attributes
593
	 * @param  lang		the language in which the description has been formulated
594
	 * @see     		#NewInstance(String, String, String)
595
	 */
596
	@Override
597
	public Feature readCsvLine(Class<Feature> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
598
		Feature newInstance = super.readCsvLine(termClass, csvLine, terms, abbrevAsId);
599
		String text = csvLine.get(4);
600
		if (text != null && text.length() >= 6){
601
			if ("1".equals(text.substring(0, 1))){newInstance.setSupportsTextData(true);};
602
			if ("1".equals(text.substring(1, 2))){newInstance.setSupportsQuantitativeData(true);};
603
			if ("1".equals(text.substring(2, 3))){newInstance.setSupportsDistribution(true);};
604
			if ("1".equals(text.substring(3, 4))){newInstance.setSupportsIndividualAssociation(true);};
605
			if ("1".equals(text.substring(4, 5))){newInstance.setSupportsTaxonInteraction(true);};
606
			if ("1".equals(text.substring(5, 6))){newInstance.setSupportsCommonTaxonName(true);};
607
			// if ("1".equals(text.substring(6, 7))){newInstance.setSupportsCategoricalData(true);};
608
			//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
609
			newInstance.getRepresentation(Language.DEFAULT()).setAbbreviatedLabel(null);
610
		}
611
		return newInstance;
612
	}
613

    
614
//******************************* STATIC METHODS *****************************************
615

    
616
	protected static Feature getTermByUuid(UUID uuid){
617
		if (termMap == null){
618
			return null;  //better return null then initialize the termMap in an unwanted way
619
			//example for an unwanted initialization: before initializing spring you may use a static method of this class.
620
			//This would result in an default terminitialization instead of a database based
621
			// term initialization
622

    
623
//			DefaultTermInitializer vocabularyStore = new DefaultTermInitializer();
624
//			vocabularyStore.initialize();
625
		}
626
			return termMap.get(uuid);
627
	}
628

    
629
	/**
630
	 * Returns the "unknown" feature. This feature allows to store values of
631
	 * {@link DescriptionElementBase description elements} even if it is momentarily
632
	 * not known what they mean.
633
	 */
634
	public static final Feature UNKNOWN(){
635
		return getTermByUuid(uuidUnknown);
636
	}
637

    
638
	/**
639
	 * Returns the "description" feature. This feature allows to handle global
640
	 * {@link DescriptionElementBase description elements} for a global {@link DescriptionBase description}.<BR>
641
	 * The "description" feature is the highest level feature.
642
	 */
643
	public static final Feature DESCRIPTION(){
644
		return getTermByUuid(uuidDescription);
645
	}
646

    
647
	/**
648
	 * Returns the "distribution" feature. This feature allows to handle only
649
	 * {@link Distribution distributions}.
650
	 *
651
	 * @see	#isSupportsDistribution()
652
	 */
653
	public static final Feature DISTRIBUTION(){
654
		return getTermByUuid(uuidDistribution);
655
	}
656

    
657
	/**
658
	 * Returns the "discussion" feature. This feature can only be described
659
	 * with {@link TextData text data}.
660
	 *
661
	 * @see	#isSupportsTextData()
662
	 */
663
	public static final Feature DISCUSSION(){
664
		return getTermByUuid(uuidDiscussion);
665
	}
666

    
667
	/**
668
	 * Returns the "ecology" feature. This feature only applies
669
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
670
	 * The "ecology" feature generalizes all other possible features concerning
671
	 * ecological matters.
672
	 */
673
	public static final Feature ECOLOGY(){
674
		return getTermByUuid(uuidEcology);
675
	}
676

    
677
	/**
678
	 * Returns the "habitat" feature. This feature only applies
679
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
680
	 * The "habitat" feature generalizes all other possible features concerning
681
	 * habitat matters.
682
	 */
683
	public static final Feature HABITAT(){
684
		return getTermByUuid(uuidHabitat);
685
	}
686

    
687

    
688
	/**
689
	 * Returns the "habitat & ecology" feature. This feature only applies
690
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
691
	 * The "habitat & ecology" feature generalizes all other possible features concerning
692
	 * habitat and ecology matters.
693
	 */
694
	public static final Feature HABITAT_ECOLOGY(){
695
		return getTermByUuid(uuidHabitatAndEcology);
696
	}
697

    
698
	/**
699
	 * Returns the "biology_ecology" feature. This feature only applies
700
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
701
	 * The "biology_ecology" feature generalizes all possible features concerning
702
	 * biological aspects of ecological matters.
703
	 *
704
	 * @see #ECOLOGY()
705
	 */
706
	public static final Feature BIOLOGY_ECOLOGY(){
707
		return getTermByUuid(uuidBiologyEcology);
708
	}
709

    
710
	/**
711
	 * Returns the "chromosome number" feature. This feature only applies
712
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
713
	 */
714
	public static final Feature CHROMOSOME_NUMBER(){
715
		return getTermByUuid(uuidChromosomeNumber);
716
	}
717

    
718

    
719
	/**
720
	 * Returns the "key" feature. This feature is the "upper" feature generalizing
721
	 * all features being used within an identification key.
722
	 */
723
	public static final Feature KEY(){
724
		return getTermByUuid(uuidKey);
725
	}
726

    
727

    
728
	/**
729
	 * Returns the "materials_examined" feature. This feature can only be described
730
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
731
	 * mentioning which material has been examined in order to accomplish
732
	 * the description. This feature applies only to
733
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
734
	 */
735
	public static final Feature MATERIALS_EXAMINED(){
736
		return getTermByUuid(uuidMaterialsExamined);
737
	}
738

    
739
	/**
740
	 * Returns the "materials_methods" feature. This feature can only be described
741
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
742
	 * mentioning which methods have been adopted to analyze the material in
743
	 * order to accomplish the description. This feature applies only to
744
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
745
	 */
746
	public static final Feature MATERIALS_METHODS(){
747
		return getTermByUuid(uuidMaterialsMethods);
748
	}
749

    
750
	/**
751
	 * Returns the "etymology" feature. This feature can only be described
752
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
753
	 * giving some information about the history of the taxon name. This feature applies only to
754
	 * {@link TaxonNameDescription taxon name descriptions}.
755
	 */
756
	public static final Feature ETYMOLOGY(){
757
		return getTermByUuid(uuidEtymology);
758
	}
759

    
760
	/**
761
	 * Returns the "diagnosis" feature. This feature can only be described
762
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}.
763
	 * This feature applies only to {@link SpecimenDescription specimen descriptions} or to
764
	 * {@link TaxonDescription taxon descriptions}.
765
	 */
766
	public static final Feature DIAGNOSIS(){
767
		return getTermByUuid(uuidDiagnosis);
768
	}
769

    
770

    
771
	/**
772
	 * Returns the "introduction" feature. This feature can only be described
773
	 * with {@link TextData text data}.
774
	 *
775
	 * @see	#isSupportsTextData()
776
	 */
777
	public static final Feature INTRODUCTION(){
778
		return getTermByUuid(uuidIntroduction);
779
	}
780

    
781
	/**
782
	 * Returns the "protologue" feature. This feature can only be described
783
	 * with {@link TextData text data} reproducing the content of the protologue
784
	 * (or some information about it) of the taxon name. This feature applies only to
785
	 * {@link TaxonNameDescription taxon name descriptions}.
786
	 *
787
	 * @see	#isSupportsTextData()
788
	 */
789
	public static final Feature PROTOLOGUE(){
790
		return getTermByUuid(uuidProtologue);
791
	}
792

    
793
	/**
794
	 * Returns the "common_name" feature. This feature allows to handle only
795
	 * {@link CommonTaxonName common names}.
796
	 *
797
	 * @see	#isSupportsCommonTaxonName()
798
	 */
799
	public static final Feature COMMON_NAME(){
800
		return getTermByUuid(uuidCommonName);
801
	}
802

    
803
	/**
804
	 * Returns the "phenology" feature. This feature can only be described
805
	 * with {@link CategoricalData categorical data} or eventually with {@link TextData text data}
806
	 * containing information time about recurring natural phenomena.
807
	 * This feature only applies to {@link TaxonDescription taxon descriptions}.<BR>
808
	 * The "phenology" feature generalizes all other possible features
809
	 * concerning time information about particular natural phenomena
810
	 * (such as "first flight of butterflies").
811
	 */
812
	public static final Feature PHENOLOGY(){
813
		return getTermByUuid(uuidPhenology);
814
	}
815

    
816
	/**
817
	 * Returns the "occurrence" feature.
818
	 */
819
	public static final Feature OCCURRENCE(){
820
		return getTermByUuid(uuidOccurrence);
821
	}
822

    
823
	/**
824
	 * Returns the "anatomy" feature.
825
	 */
826
	public static final Feature ANATOMY(){
827
		return getTermByUuid(uuidAnatomy);
828
	}
829
	/**
830
	 * Returns the "hostplant" feature.
831
	 */
832
	public static final Feature HOSTPLANT(){
833
		return getTermByUuid(uuidHostPlant);
834
	}
835
	/**
836
	 * Returns the "pathogen agent" feature.
837
	 */
838
	public static final Feature PATHOGEN_AGENT(){
839
		return getTermByUuid(uuidPathogenAgent);
840
	}
841

    
842
	/**
843
	 * Returns the "citation" feature. This feature can only be described
844
	 * with {@link TextData text data}.
845
	 *
846
	 * @see	#isSupportsTextData()
847
	 */
848
	public static final Feature CITATION(){
849
		return getTermByUuid(uuidCitation);
850
	}
851

    
852
	/**
853
	 * Returns the "additional_publication" feature. This feature can only be
854
	 * described with {@link TextData text data} with information about a
855
	 * publication where a {@link TaxonNameBase taxon name} has also been published
856
	 * but which is not the {@link TaxonNameBase#getNomenclaturalReference() nomenclatural reference}.
857
	 * This feature applies only to {@link TaxonNameDescription taxon name descriptions}.
858
	 *
859
	 * @see	#isSupportsTextData()
860
	 */
861
	public static final Feature ADDITIONAL_PUBLICATION(){
862
		return getTermByUuid(uuidAdditionalPublication);
863
	}
864

    
865

    
866
	/**
867
	 * Returns the "uses" feature. This feature only applies
868
	 * to {@link TaxonDescription taxon descriptions}.<BR>
869
	 * The "uses" feature generalizes all other possible features concerning
870
	 * particular uses (for instance "industrial use of seeds").
871
	 */
872
	public static final Feature USES(){
873
		return getTermByUuid(uuidUses);
874
	}
875

    
876
	public static final Feature USERECORD(){
877
		return getTermByUuid(uuidUseRecord);
878
	}
879

    
880

    
881
	/**
882
	 * Returns the "conservation" feature. This feature only applies
883
	 * to {@link SpecimenDescription specimen descriptions} and generalizes
884
	 * methods and conditions for the conservation of {@link Specimen specimens}.<BR>
885
	 */
886
	public static final Feature CONSERVATION(){
887
		return getTermByUuid(uuidConservation);
888
	}
889

    
890

    
891
	/**
892
	 * Returns the "cultivation" feature.
893
	 */
894
	public static final Feature CULTIVATION(){
895
		return getTermByUuid(uuidCultivation);
896
	}
897

    
898

    
899
	/**
900
	 * Returns the "image" feature.
901
	 */
902
	public static final Feature IMAGE(){
903
		return getTermByUuid(uuidImage);
904
	}
905

    
906
	/**
907
	 * Returns the "individuals association" feature.
908
	 */
909
	public static final Feature INDIVIDUALS_ASSOCIATION(){
910
		Feature individuals_association =  getTermByUuid(uuidIndividualsAssociation);
911
		Set<Feature> generalizationOf = new HashSet<Feature>();
912
		generalizationOf.add(SPECIMEN());
913
		generalizationOf.add(OBSERVATION());
914
		individuals_association.setGeneralizationOf(generalizationOf);
915
		return individuals_association;
916

    
917
	}
918

    
919
	public static final Feature SPECIMEN(){
920
		return getTermByUuid(uuidSpecimen);
921
	}
922

    
923
	public static final Feature OBSERVATION(){
924
		return getTermByUuid(uuidObservation);
925
	}
926

    
927
	/**
928
	 * The status of a taxon. Usually the status should be determined within a {@link Distribution distribution}.
929
	 * If this is not possible for some reason (e.g. the area is not well defined) the status feature
930
	 * may be used.
931
	 * @return
932
	 */
933
	public static final Feature STATUS(){
934
		return getTermByUuid(uuidStatus);
935
	}
936

    
937
	public static final Feature SYSTEMATICS(){
938
		return getTermByUuid(uuidSystematics);
939
	}
940

    
941
	/**
942
	 * Returns the "hybrid_parent" feature. This feature can only be used
943
	 * by {@link TaxonInteraction taxon interactions}.<BR>
944
	 * <P>
945
	 * Note: It must be distinguished between hybrid relationships as
946
	 * relevant nomenclatural relationships between {@link BotanicalName plant names}
947
	 * on the one side and the biological relation between two {@link Taxon taxa}
948
	 * as it is here the case on the other one.
949
	 *
950
	 * @see	#isSupportsTaxonInteraction()
951
	 * @see	HybridRelationshipType
952
	 */
953
	public static final Feature HYBRID_PARENT(){
954
		//TODO
955
		logger.warn("HYBRID_PARENT not yet implemented");
956
		return null;
957
	}
958

    
959
	@Override
960
	protected void setDefaultTerms(TermVocabulary<Feature> termVocabulary) {
961
		if (termMap == null){  //needed because there are multiple feature vocabularies
962
			termMap = new HashMap<UUID, Feature>();
963
		}
964
		for (Feature term : termVocabulary.getTerms()){
965
			termMap.put(term.getUuid(), term);
966
		}
967
	}
968

    
969
}
(8-8/36)