Project

General

Profile

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

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

    
39
import org.apache.log4j.Logger;
40
import org.hibernate.annotations.Cascade;
41
import org.hibernate.annotations.CascadeType;
42
import org.hibernate.annotations.Parameter;
43
import org.hibernate.annotations.Type;
44
import org.hibernate.envers.Audited;
45

    
46
import eu.etaxonomy.cdm.model.common.CdmClass;
47
import eu.etaxonomy.cdm.model.common.Language;
48
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
49
import eu.etaxonomy.cdm.model.name.TaxonName;
50
import eu.etaxonomy.cdm.model.term.DefinedTerm;
51
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
52
import eu.etaxonomy.cdm.model.term.Representation;
53
import eu.etaxonomy.cdm.model.term.TermTree;
54
import eu.etaxonomy.cdm.model.term.TermType;
55
import eu.etaxonomy.cdm.model.term.TermVocabulary;
56

    
57

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

    
116
	private static final long serialVersionUID = 6754598791831848704L;
117
	@SuppressWarnings("unused")
118
    private static final Logger logger = Logger.getLogger(Feature.class);
119

    
120
	protected static Map<UUID, Feature> termMap = null;
121

    
122
    @XmlAttribute(name ="availableFor")
123
    @NotNull
124
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumSetUserType",
125
        parameters = {@Parameter(name = "enumClass", value = "eu.etaxonomy.cdm.model.common.CdmClass")}
126
    )
127
    private EnumSet<CdmClass> availableFor = EnumSet.noneOf(CdmClass.class);
128

    
129
    @XmlAttribute(name ="supportedDataTypes")
130
    @NotNull
131
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumSetUserType",
132
        parameters = {@Parameter(name = "enumClass", value = "eu.etaxonomy.cdm.model.common.CdmClass")}
133
    )
134
    private EnumSet<CdmClass> supportedDataTypes = EnumSet.of(CdmClass.TEXT_DATA);  //by default TextData should always be supported
135

    
136

    
137
    /* for M:M see #4843 */
138
	@ManyToMany(fetch = FetchType.LAZY)
139
    @JoinTable(name="DefinedTermBase_RecommendedModifierEnumeration")
140
	private final Set<TermVocabulary<DefinedTerm>> recommendedModifierEnumeration = new HashSet<>();
141

    
142
	@ManyToMany(fetch = FetchType.LAZY)
143
    @JoinTable(name="DefinedTermBase_StatisticalMeasure")
144
	private final Set<StatisticalMeasure> recommendedStatisticalMeasures = new HashSet<>();
145

    
146
	/* for M:M see #4843 */
147
	@ManyToMany(fetch = FetchType.LAZY)
148
	@JoinTable(name="DefinedTermBase_SupportedCategoricalEnumeration")
149
	private final Set<TermVocabulary<State>> supportedCategoricalEnumerations = new HashSet<>();
150

    
151

    
152
	@ManyToMany(fetch = FetchType.LAZY)
153
    @JoinTable(name="DefinedTermBase_MeasurementUnit")
154
	private final Set<MeasurementUnit> recommendedMeasurementUnits = new HashSet<>();
155

    
156

    
157
    //copy from RelationshipTermBase
158
	@XmlElementWrapper(name = "InverseRepresentations")
159
    @XmlElement(name = "Representation")
160
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval=true)
161
    @JoinTable(name="DefinedTermBase_InverseRepresentation",  //see also RelationshipTermBase.inverseRepresentations
162
        joinColumns=@JoinColumn(name="DefinedTermBase_id")
163
        //  inverseJoinColumns
164
    )
165
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
166
//    @IndexedEmbedded(depth = 2)
167
    private Set<Representation> inverseRepresentations = new HashSet<>();
168

    
169
    private static final UUID uuidUnknown = UUID.fromString("910307f1-dc3c-452c-a6dd-af5ac7cd365c");
170
    public static final UUID uuidDescription = UUID.fromString("9087cdcd-8b08-4082-a1de-34c9ba9fb493");
171
    private static final UUID uuidDistribution = UUID.fromString("9fc9d10c-ba50-49ee-b174-ce83fc3f80c6");
172
    private static final UUID uuidDistributionGeneral = UUID.fromString("fd8c64f0-6ea5-44b0-9f70-e95833d6076e");
173
    private static final UUID uuidEcology = UUID.fromString("aa923827-d333-4cf5-9a5f-438ae0a4746b");
174
    public static final UUID uuidHabitat = UUID.fromString("fb16929f-bc9c-456f-9d40-dec987b36438");
175
    private static final UUID uuidHabitatAndEcology = UUID.fromString("9fdc4663-4d56-47d0-90b5-c0bf251bafbb");
176
    private static final UUID uuidChromosomeNumber = UUID.fromString("6f677e98-d8d5-4bc5-80bf-affdb7e3945a");
177

    
178
    private static final UUID uuidBiologyEcology = UUID.fromString("9832e24f-b670-43b4-ac7c-20a7261a1d8c");
179
    private static final UUID uuidKey = UUID.fromString("a677f827-22b9-4205-bb37-11cb48dd9106");
180
    private static final UUID uuidMaterialsExamined = UUID.fromString("7c0c7571-a864-47c1-891d-01f59000dae1");
181
    private static final UUID uuidMaterialsMethods = UUID.fromString("1e87d9c3-0844-4a03-9686-773e2ccb3ab6");
182
    private static final UUID uuidEtymology = UUID.fromString("dd653d48-355c-4aec-a4e7-724f6eb29f8d");
183
    private static final UUID uuidDiagnosis = UUID.fromString("d43d8501-ceab-4caa-9e51-e87138528fac");
184
    private static final UUID uuidProtologue = UUID.fromString("71b356c5-1e3f-4f5d-9b0f-c2cf8ae7779f");
185
    public static final UUID uuidCommonName = UUID.fromString("fc810911-51f0-4a46-ab97-6562fe263ae5");
186
    private static final UUID uuidPhenology = UUID.fromString("a7786d3e-7c58-4141-8416-346d4c80c4a2");
187
    private static final UUID uuidOccurrence = UUID.fromString("5deff505-1a32-4817-9a74-50e6936fd630");
188
    private static final UUID uuidCitation = UUID.fromString("99b2842f-9aa7-42fa-bd5f-7285311e0101");
189
    private static final UUID uuidAdditionalPublication = UUID.fromString("2c355c16-cb04-4858-92bf-8da8d56dea95");
190
    public static final UUID uuidUses = UUID.fromString("e5374d39-b210-47c7-bec1-bee05b5f1cb6");
191
    private static final UUID uuidConservation = UUID.fromString("4518fc20-2492-47de-b345-777d2b83c9cf");
192
    private static final UUID uuidCultivation = UUID.fromString("e28965b2-a367-48c5-b954-8afc8ac2c69b");
193
    private static final UUID uuidIntroduction = UUID.fromString("e75255ca-8ff4-4905-baad-f842927fe1d3");
194
    private static final UUID uuidDiscussion = UUID.fromString("d3c4cbb6-0025-4322-886b-cd0156753a25");
195
    public static final UUID uuidImage = UUID.fromString("84193b2c-327f-4cce-90ef-c8da18fd5bb5");
196
    private static final UUID uuidAnatomy = UUID.fromString("94213b2c-e67a-4d37-25ef-e8d316edfba1");
197
    private static final UUID uuidHostPlant = UUID.fromString("6e9de1d5-05f0-40d5-8786-2fe30d0d894d");
198
    private static final UUID uuidPathogenAgent = UUID.fromString("002d05f2-fd72-49f1-ba4d-196cf09240b5");
199
    private static final UUID uuidIndividualsAssociation = UUID.fromString("e2308f37-ddc5-447d-b483-5e2171dd85fd");
200
    public static final UUID uuidSpecimen = UUID.fromString("8200e050-d5fd-4cac-8a76-4b47afb13809");
201
    private static final UUID uuidObservation = UUID.fromString("f59e747d-0b4f-4bf7-b69a-cbd50bc78595");
202
    public static final UUID uuidStatus = UUID.fromString("86d40635-2a63-4ad6-be75-9faa4a6a57fb");
203
    private static final UUID uuidSystematics = UUID.fromString("bd9aca17-cd0e-4418-a3a1-1a4b80dbc162");
204
    private static final UUID uuidUseRecord = UUID.fromString("8125a59d-b4d5-4485-89ea-67306297b599");
205
    private static final UUID uuidNotes = UUID.fromString("b5780b45-6439-4f3c-9818-d89d26d36eb2");
206
    public static final UUID uuidLifeform = UUID.fromString("db9228d3-8bbf-4460-abfe-0b1326c82f8e");
207
    public static final UUID uuidFloweringPeriod = UUID.fromString("03710cb5-606e-444a-a3e6-594268e3cc47");
208
    public static final UUID uuidFruitingPeriod = UUID.fromString("04aa8993-24b4-43e3-888c-5afaa733376e");
209
    public static final UUID uuidAltitude = UUID.fromString("1a28ed59-e15f-4001-b5c2-ea89f0012671");
210

    
211
/* ***************** CONSTRUCTOR AND FACTORY METHODS **********************************/
212

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

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

    
238
// ********************** CONSTRUCTOR ************************/
239

    
240
    //for hibernate use only
241
    @Deprecated
242
    protected Feature() {
243
        super(TermType.Feature);
244
    }
245

    
246
    /**
247
     * Class constructor: creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
248
     * a label and a label abbreviation.
249
     *
250
     * @param   term         the string (in the default language) describing the
251
     *                       new feature to be created
252
     * @param   label        the string identifying the new feature to be created
253
     * @param   labelAbbrev  the string identifying (in abbreviated form) the
254
     *                       new feature to be created
255
     * @see                  #Feature()
256
     */
257
    protected Feature(String term, String label, String labelAbbrev) {
258
        super(TermType.Feature, term, label, labelAbbrev);
259
    }
260

    
261
/* *************************************************************************************/
262

    
263
	@Override
264
	public void resetTerms(){
265
		termMap = null;
266
	}
267

    
268

    
269
	/**
270
     * If this feature is available for {@link TaxonDescription taxon descriptions}.
271
     */
272
    @XmlElement(name = "AvailableForTaxon")
273
    public boolean isAvailableForTaxon() {
274
        return availableFor.contains(CdmClass.TAXON);
275
    }
276
    /**
277
     * @see #isAvailableForTaxon()
278
     */
279
    public void setAvailableForTaxon(boolean availableForTaxon) {
280
        setAvailableFor(CdmClass.TAXON, availableForTaxon);
281
    }
282

    
283

    
284
    /**
285
     * If this feature is available for {@link NameDescription name descriptions}.
286
     */
287
    @XmlElement(name = "AvailableForTaxonName")
288
    public boolean isAvailableForTaxonName() {
289
        return availableFor.contains(CdmClass.TAXON_NAME);
290
    }
291
    /**
292
     * @see #isAvailableForTaxon()
293
     */
294
    public void setAvailableForTaxonName(boolean availableForTaxonName) {
295
        setAvailableFor(CdmClass.TAXON_NAME, availableForTaxonName);
296
    }
297

    
298
    /**
299
     * If this feature is available for {@link SpecimenDescription specimen descriptions}.
300
     */
301
    @XmlElement(name = "AvailableForOccurrence")
302
    public boolean isAvailableForOccurrence() {
303
        return availableFor.contains(CdmClass.OCCURRENCE);
304
    }
305
    /**
306
     * @see #isAvailableForOccurrence()
307
     */
308
    public void setAvailableForOccurrence(boolean availableForOccurrence) {
309
        setAvailableFor(CdmClass.OCCURRENCE, availableForOccurrence);
310
    }
311

    
312

    
313
	/**
314
	 * Returns the boolean value of the flag indicating whether <i>this</i>
315
	 * feature can be described with {@link QuantitativeData quantitative data} (true)
316
	 * or not (false). If this flag is set <i>this</i> feature can only apply to
317
	 * {@link TaxonDescription taxon descriptions} or {@link SpecimenDescription specimen descriptions}.
318
	 *
319
	 * @return  the boolean value of the supportsQuantitativeData flag
320
	 */
321
	@XmlElement(name = "SupportsQuantitativeData")
322
	public boolean isSupportsQuantitativeData() {
323
	    return supportedDataTypes.contains(CdmClass.QUANTITATIVE_DATA);
324
	}
325

    
326
	/**
327
	 * @see	#isSupportsQuantitativeData()
328
	 */
329
	public void setSupportsQuantitativeData(boolean supportsQuantitativeData) {
330
        setSupportedClass(CdmClass.QUANTITATIVE_DATA, supportsQuantitativeData);
331
	}
332

    
333
	/**
334
	 * Returns the boolean value of the flag indicating whether <i>this</i>
335
	 * feature can be described with {@link TextData text data} (true)
336
	 * or not (false).
337
	 *
338
	 * @return  the boolean value of the supportsTextData flag
339
	 */
340
	@XmlElement(name = "SupportsTextData")
341
	public boolean isSupportsTextData() {
342
	    return supportedDataTypes.contains(CdmClass.TEXT_DATA);
343
	}
344

    
345
	/**
346
	 * @see	#isSupportsTextData()
347
	 */
348
	public void setSupportsTextData(boolean supportsTextData) {
349
        setSupportedClass(CdmClass.TEXT_DATA, supportsTextData);
350
	}
351

    
352
	/**
353
	 * Returns the boolean value of the flag indicating whether <i>this</i>
354
	 * feature can be described with {@link Distribution distribution} objects
355
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
356
	 * is the {@link #DISTRIBUTION() distribution feature}.
357
	 *
358
	 * @return  the boolean value of the supportsDistribution flag
359
	 */
360
	@XmlElement(name = "SupportsDistribution")
361
	public boolean isSupportsDistribution() {
362
	      return supportedDataTypes.contains(CdmClass.DISTRIBUTION);
363
	}
364

    
365
	/**
366
	 * @see	#isSupportsDistribution()
367
	 */
368
	public void setSupportsDistribution(boolean supportsDistribution) {
369
        setSupportedClass(CdmClass.DISTRIBUTION, supportsDistribution);
370
	}
371

    
372
	/**
373
	 * Returns the boolean value of the flag indicating whether <i>this</i>
374
	 * feature can be described with {@link IndividualsAssociation individuals associations}
375
	 * (true) or not (false).
376
	 *
377
	 * @return  the boolean value of the supportsIndividualAssociation flag
378
	 */
379
	@XmlElement(name = "SupportsIndividualAssociation")
380
	public boolean isSupportsIndividualAssociation() {
381
	      return supportedDataTypes.contains(CdmClass.INDIVIDUALS_ASSOCIATION);
382
	}
383

    
384
	/**
385
	 * @see	#isSupportsIndividualAssociation()
386
	 */
387
	public void setSupportsIndividualAssociation(
388
			boolean supportsIndividualAssociation) {
389
        setSupportedClass(CdmClass.INDIVIDUALS_ASSOCIATION, supportsIndividualAssociation);
390
	}
391

    
392
	/**
393
	 * Returns the boolean value of the flag indicating whether <i>this</i>
394
	 * feature can be described with {@link TaxonInteraction taxon interactions}
395
	 * (true) or not (false).
396
	 *
397
	 * @return  the boolean value of the supportsTaxonInteraction flag
398
	 */
399
	@XmlElement(name = "SupportsTaxonInteraction")
400
	public boolean isSupportsTaxonInteraction() {
401
	      return supportedDataTypes.contains(CdmClass.TAXON_INTERACTION);
402
	}
403

    
404
	/**
405
	 * @see	#isSupportsTaxonInteraction()
406
	 */
407
	public void setSupportsTaxonInteraction(boolean supportsTaxonInteraction) {
408
        setSupportedClass(CdmClass.TAXON_INTERACTION, supportsTaxonInteraction);
409
	}
410

    
411
	/**
412
	 * Returns the boolean value of the flag indicating whether <i>this</i>
413
	 * feature can be described with {@link CommonTaxonName common names}
414
	 * (true) or not (false). This flag is set if and only if <i>this</i> feature
415
	 * is the {@link #COMMON_NAME() common name feature}.
416
	 *
417
	 * @return  the boolean value of the supportsCommonTaxonName flag
418
	 */
419
	@XmlElement(name = "SupportsCommonTaxonName")
420
	public boolean isSupportsCommonTaxonName() {
421
	      return supportedDataTypes.contains(CdmClass.COMMON_TAXON_NAME);
422
	}
423

    
424
	/**
425
	 * @see	#isSupportsTaxonInteraction()
426
	 */
427
	public void setSupportsCommonTaxonName(boolean supportsCommonTaxonName) {
428
        setSupportedClass(CdmClass.COMMON_TAXON_NAME, supportsCommonTaxonName);
429
	}
430

    
431
	/**
432
	 * Returns the boolean value of the flag indicating whether <i>this</i>
433
	 * feature can be described with {@link CategoricalData categorical data}
434
	 * (true) or not (false).
435
	 *
436
	 * @return  the boolean value of the supportsCategoricalData flag
437
	 */
438
	@XmlElement(name = "SupportsCategoricalData")
439
	public boolean isSupportsCategoricalData() {
440
		return supportedDataTypes.contains(CdmClass.CATEGORICAL_DATA);
441
	}
442

    
443
	/**
444
	 * @see	#supportsCategoricalData()
445
	 */
446
	public void setSupportsCategoricalData(boolean supportsCategoricalData) {
447
        setSupportedClass(CdmClass.CATEGORICAL_DATA, supportsCategoricalData);
448
	}
449

    
450
	/**
451
     * Returns the boolean value of the flag indicating whether <i>this</i>
452
     * feature can be described with {@link TemporalData temporalData}
453
     * (true) or not (false).
454
     *
455
     * @return  the boolean value of the supportsTemporalData flag
456
     */
457
    @XmlElement(name = "SupportsTemporalData")
458
    public boolean isSupportsTemporalData() {
459
          return supportedDataTypes.contains(CdmClass.TEMPORAL_DATA);
460
    }
461

    
462
    /**
463
     * @see #isSupportsTemporalData()
464
     */
465
    public void setSupportsTemporalData(boolean supportsTemporalData) {
466
        setSupportedClass(CdmClass.TEMPORAL_DATA, supportsTemporalData);
467
    }
468

    
469
    /**
470
     * Sets the value for supported classes
471
     * @param cdmClass the supported class
472
     * @param value the value if it is supported (<code>true</code>) or not (<code>false</code>)
473
     */
474
    private void setSupportedClass(CdmClass cdmClass, boolean value) {
475
        if (value){
476
            this.supportedDataTypes.add(cdmClass);
477
        }else{
478
            this.supportedDataTypes.remove(cdmClass);
479
        }
480
    }
481

    
482
    /**
483
     * Sets the value for supported classes
484
     * @param cdmClass the supported class
485
     * @param value the value if it is supported (<code>true</code>) or not (<code>false</code>)
486
     */
487
    private void setAvailableFor(CdmClass cdmClass, boolean value) {
488
        if (value){
489
            this.availableFor.add(cdmClass);
490
        }else{
491
            this.availableFor.remove(cdmClass);
492
        }
493
    }
494

    
495
    /**
496
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the
497
	 * {@link Modifier modifiers} recommended to be used for {@link DescriptionElementBase description elements}
498
	 * with <i>this</i> feature.
499
	 *
500
	 */
501
	@XmlElementWrapper(name = "RecommendedModifierEnumerations")
502
	@XmlElement(name = "RecommendedModifierEnumeration")
503
	@XmlIDREF
504
	@XmlSchemaType(name = "IDREF")
505
	public Set<TermVocabulary<DefinedTerm>> getRecommendedModifierEnumeration() {
506
		return recommendedModifierEnumeration;
507
	}
508

    
509
	/**
510
	 * Adds a {@link TermVocabulary term vocabulary} (with {@link Modifier modifiers}) to the set of
511
	 * {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies} assigned
512
	 * to <i>this</i> feature.
513
	 *
514
	 * @param recommendedModifierEnumeration	the term vocabulary to be added
515
	 * @see    	   								#getRecommendedModifierEnumeration()
516
	 */
517
	public void addRecommendedModifierEnumeration(
518
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
519
		this.recommendedModifierEnumeration.add(recommendedModifierEnumeration);
520
	}
521
	/**
522
	 * Removes one element from the set of {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies}
523
	 * assigned to <i>this</i> feature.
524
	 *
525
	 * @param  recommendedModifierEnumeration	the term vocabulary which should be removed
526
	 * @see     								#getRecommendedModifierEnumeration()
527
	 * @see     								#addRecommendedModifierEnumeration(TermVocabulary)
528
	 */
529
	public void removeRecommendedModifierEnumeration(
530
			TermVocabulary<DefinedTerm> recommendedModifierEnumeration) {
531
		this.recommendedModifierEnumeration.remove(recommendedModifierEnumeration);
532
	}
533

    
534
	/**
535
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
536
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
537
	 */
538
	@XmlElementWrapper(name = "RecommendedStatisticalMeasures")
539
	@XmlElement(name = "RecommendedStatisticalMeasure")
540
	@XmlIDREF
541
	@XmlSchemaType(name = "IDREF")
542
	public Set<StatisticalMeasure> getRecommendedStatisticalMeasures() {
543
		return recommendedStatisticalMeasures;
544
	}
545

    
546
	/**
547
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
548
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
549
	 * to <i>this</i> feature.
550
	 *
551
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
552
	 * @see    	   							#getRecommendedStatisticalMeasures()
553
	 */
554
	public void addRecommendedStatisticalMeasure(
555
			StatisticalMeasure recommendedStatisticalMeasure) {
556
		this.recommendedStatisticalMeasures.add(recommendedStatisticalMeasure);
557
	}
558
	/**
559
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
560
	 * assigned to <i>this</i> feature.
561
	 *
562
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
563
	 * @see     								#getRecommendedStatisticalMeasures()
564
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
565
	 */
566
	public void removeRecommendedStatisticalMeasure(
567
			StatisticalMeasure recommendedStatisticalMeasure) {
568
		this.recommendedStatisticalMeasures.remove(recommendedStatisticalMeasure);
569
	}
570

    
571
	/**
572
	 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
573
	 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
574
	 */
575
	@XmlElementWrapper(name = "RecommendedMeasurementUnits")
576
	@XmlElement(name = "RecommendedMeasurementUnit")
577
	@XmlIDREF
578
	@XmlSchemaType(name = "IDREF")
579
	public Set<MeasurementUnit> getRecommendedMeasurementUnits() {
580
		return recommendedMeasurementUnits;
581
	}
582

    
583
	/**
584
	 * Adds a {@link StatisticalMeasure statistical measure} to the set of
585
	 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
586
	 * to <i>this</i> feature.
587
	 *
588
	 * @param recommendedStatisticalMeasure	the statistical measure to be added
589
	 * @see    	   							#getRecommendedStatisticalMeasures()
590
	 */
591
	public void addRecommendedMeasurementUnit(
592
			MeasurementUnit recommendedMeasurementUnit) {
593
		this.recommendedMeasurementUnits.add(recommendedMeasurementUnit);
594
	}
595
	/**
596
	 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
597
	 * assigned to <i>this</i> feature.
598
	 *
599
	 * @param  recommendedStatisticalMeasure	the statistical measure which should be removed
600
	 * @see     								#getRecommendedStatisticalMeasures()
601
	 * @see     								#addRecommendedStatisticalMeasure(StatisticalMeasure)
602
	 */
603
	public void removeRecommendedMeasurementUnit(
604
			MeasurementUnit recommendedMeasurementUnit) {
605
		this.recommendedMeasurementUnits.remove(recommendedMeasurementUnit);
606
	}
607

    
608
	/**
609
	 * Returns the set of {@link TermVocabulary term vocabularies} containing the list of
610
	 * possible {@link State states} to be used in {@link CategoricalData categorical data}
611
	 * with <i>this</i> feature.
612
	 *
613
	 */
614
	@XmlElementWrapper(name = "SupportedCategoricalEnumerations")
615
	@XmlElement(name = "SupportedCategoricalEnumeration")
616
	@XmlIDREF
617
	@XmlSchemaType(name = "IDREF")
618
	public Set<TermVocabulary<State>> getSupportedCategoricalEnumerations() {
619
		return supportedCategoricalEnumerations;
620
	}
621

    
622
	/**
623
	 * Adds a {@link TermVocabulary term vocabulary} to the set of
624
	 * {@link #getSupportedCategoricalEnumerations() supported state vocabularies} assigned
625
	 * to <i>this</i> feature.
626
	 *
627
	 * @param supportedCategoricalEnumeration	the term vocabulary which should be removed
628
	 * @see    	   								#getSupportedCategoricalEnumerations()
629
	 */
630
	public void addSupportedCategoricalEnumeration(
631
			TermVocabulary<State> supportedCategoricalEnumeration) {
632
		this.supportedCategoricalEnumerations.add(supportedCategoricalEnumeration);
633
	}
634
	/**
635
	 * Removes one element from the set of {@link #getSupportedCategoricalEnumerations() supported state vocabularies}
636
	 * assigned to <i>this</i> feature.
637
	 *
638
	 * @param  supportedCategoricalEnumeration	the term vocabulary which should be removed
639
	 * @see     								#getSupportedCategoricalEnumerations()
640
	 * @see     								#addSupportedCategoricalEnumeration(TermVocabulary)
641
	 */
642
	public void removeSupportedCategoricalEnumeration(
643
			TermVocabulary<State> supportedCategoricalEnumeration) {
644
		this.supportedCategoricalEnumerations.remove(supportedCategoricalEnumeration);
645
	}
646

    
647
	@XmlElement(name = "KindOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
648
    @XmlIDREF
649
    @XmlSchemaType(name = "IDREF")
650
    @Override
651
	public Feature getKindOf(){
652
		return super.getKindOf();
653
	}
654

    
655
	@Override
656
    public void setKindOf(Feature kindOf){
657
		super.setKindOf(kindOf);
658
	}
659

    
660
	@Override
661
    @XmlElement(name = "PartOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
662
	@XmlIDREF
663
    @XmlSchemaType(name = "IDREF")
664
	public Feature getPartOf(){
665
		return super.getPartOf();
666
	}
667

    
668
	@Override
669
    public void setPartOf(Feature partOf){
670
		super.setPartOf(partOf);
671
	}
672

    
673
	@Override
674
    @XmlElementWrapper(name = "Generalizations", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
675
	@XmlElement(name = "GeneralizationOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
676
    @XmlIDREF
677
    @XmlSchemaType(name = "IDREF")
678
	public Set<Feature> getGeneralizationOf(){
679
		return super.getGeneralizationOf();
680
	}
681

    
682
	@Override
683
    protected void setGeneralizationOf(Set<Feature> value){
684
		super.setGeneralizationOf(value);
685
	}
686

    
687
	@Override
688
    @XmlElementWrapper(name = "Includes", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
689
	@XmlElement(name = "Include", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
690
	@XmlIDREF
691
    @XmlSchemaType(name = "IDREF")
692
	public Set<Feature> getIncludes(){
693
		return super.getIncludes();
694
	}
695

    
696
	@Override
697
    protected void setIncludes(Set<Feature> includes) {
698
		super.setIncludes(includes);
699
	}
700

    
701
// ***************** Invers Label *****************************************/
702

    
703
	public Set<Representation> getInverseRepresentations() {
704
        return inverseRepresentations;
705
    }
706
    public void addInverseRepresentation(Representation inverseRepresentation) {
707
        this.inverseRepresentations.add(inverseRepresentation);
708
    }
709
    public void removeInverseRepresentation(Representation inverseRepresentation) {
710
        this.inverseRepresentations.remove(inverseRepresentation);
711
    }
712
    /*
713
     * Inverse representation convenience methods similar to TermBase.xxx
714
     * @see eu.etaxonomy.cdm.model.term.TermBase#getLabel()
715
     */
716
    @Transient
717
    public String getInverseLabel() {
718
        if(getInverseLabel(Language.DEFAULT()) != null){
719
            return this.getInverseRepresentation(Language.DEFAULT()).getLabel();
720
        }else{
721
            for (Representation r : inverseRepresentations){
722
                return r.getLabel();
723
            }
724
        }
725
        return super.getUuid().toString();
726
    }
727
    public String getInverseLabel(Language lang) {
728
        Representation r = this.getInverseRepresentation(lang);
729
        if(r==null){
730
            return null;
731
        }else{
732
            return r.getLabel();
733
        }
734
    }
735
    public Representation getInverseRepresentation(Language lang) {
736
        Representation result = null;
737
        for (Representation repr : this.getInverseRepresentations()){
738
            if (lang.equals(repr.getLanguage())){
739
                result = repr;
740
            }
741
        }
742
        return result;
743
    }
744
// ****************** END INVERS REPRESENTATION **************************/
745

    
746
	/**
747
	 * Creates and returns a new feature instance on the basis of a given string
748
	 * list (containing an UUID, an URI, a label and a description) and a given
749
	 * {@link Language language} to be associated with the description. Furthermore
750
	 * the flags concerning the supported subclasses of {@link DescriptionElementBase description elements}
751
	 * are set according to a particular string belonging to the given
752
	 * string list.<BR>
753
	 * This method overrides the readCsvLine method from {@link DefinedTermBase#readCsvLine(List, Language) DefinedTermBase}.
754
	 *
755
	 * @param  csvLine	the string list with elementary information for attributes
756
	 * @param  lang		the language in which the description has been formulated
757
	 * @see     		#NewInstance(String, String, String)
758
	 */
759
	@Override
760
	public Feature readCsvLine(Class<Feature> termClass, List<String> csvLine, TermType termType,
761
	        @SuppressWarnings("rawtypes") Map<UUID,DefinedTermBase> terms, boolean abbrevAsId) {
762
		Feature newInstance = super.readCsvLine(termClass, csvLine, termType, terms, abbrevAsId);
763

    
764
		//supported datatypes
765
		String text = csvLine.get(4);
766
		if (text != null && text.length() == 8){
767
			if ("1".equals(text.substring(0, 1))){newInstance.setSupportsTextData(true);}
768
			if ("1".equals(text.substring(1, 2))){newInstance.setSupportsQuantitativeData(true);}
769
			if ("1".equals(text.substring(2, 3))){newInstance.setSupportsDistribution(true);}
770
			if ("1".equals(text.substring(3, 4))){newInstance.setSupportsIndividualAssociation(true);}
771
			if ("1".equals(text.substring(4, 5))){newInstance.setSupportsTaxonInteraction(true);}
772
			if ("1".equals(text.substring(5, 6))){newInstance.setSupportsCommonTaxonName(true);}
773
			if ("1".equals(text.substring(6, 7))){newInstance.setSupportsCategoricalData(true);}
774
			if ("1".equals(text.substring(7, 8))){newInstance.setSupportsTemporalData(true);}
775
		}else{
776
		    throw new IllegalStateException("Supported XXX must exist for all 8 subclasses");
777
		}
778

    
779
		//availableFor
780
        text = csvLine.get(5);
781
        if (text != null && text.length() == 3){
782
            if ("1".equals(text.substring(0, 1))){newInstance.setAvailableForTaxon(true);}
783
            if ("1".equals(text.substring(1, 2))){newInstance.setAvailableForOccurrence(true);}
784
            if ("1".equals(text.substring(2, 3))){newInstance.setAvailableForTaxonName(true);}
785
        }else{
786
            throw new IllegalStateException("AvailableFor XXX must exist for all 3 classes");
787
        }
788

    
789
        //abbrev label - 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
790
        newInstance.getRepresentation(Language.DEFAULT()).setAbbreviatedLabel(null);
791
		return newInstance;
792
	}
793

    
794
//******************************* STATIC METHODS *****************************************
795

    
796
	protected static Feature getTermByUuid(UUID uuid){
797
	    if (termMap == null || termMap.isEmpty()){
798
            return getTermByClassAndUUID(Feature.class, uuid);
799
        } else {
800
			return termMap.get(uuid);
801
        }
802
	}
803

    
804
	/**
805
	 * Returns the "unknown" feature. This feature allows to store values of
806
	 * {@link DescriptionElementBase description elements} even if it is momentarily
807
	 * not known what they mean.
808
	 */
809
	public static final Feature UNKNOWN(){
810
		return getTermByUuid(uuidUnknown);
811
	}
812

    
813
	/**
814
	 * Returns the "description" feature. This feature allows to handle global
815
	 * {@link DescriptionElementBase description elements} for a global {@link DescriptionBase description}.<BR>
816
	 * The "description" feature is the highest level feature.
817
	 */
818
	public static final Feature DESCRIPTION(){
819
		return getTermByUuid(uuidDescription);
820
	}
821

    
822
	/**
823
	 * Returns the "distribution" feature. This feature allows to handle only
824
	 * {@link Distribution distributions}.
825
	 *
826
	 * @see	#isSupportsDistribution()
827
	 */
828
	public static final Feature DISTRIBUTION(){
829
		return getTermByUuid(uuidDistribution);
830
	}
831

    
832
    /**
833
     * Returns the feature for general text-based
834
     * distributions
835
     */
836
    public static final Feature DISTRIBUTION_GENERAL(){
837
        return getTermByUuid(uuidDistributionGeneral);
838
    }
839

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

    
850
	/**
851
	 * Returns the "ecology" feature. This feature only applies
852
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
853
	 * The "ecology" feature generalizes all other possible features concerning
854
	 * ecological matters.
855
	 */
856
	public static final Feature ECOLOGY(){
857
		return getTermByUuid(uuidEcology);
858
	}
859

    
860
	/**
861
	 * Returns the "habitat" feature. This feature only applies
862
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
863
	 * The "habitat" feature generalizes all other possible features concerning
864
	 * habitat matters.
865
	 */
866
	public static final Feature HABITAT(){
867
		return getTermByUuid(uuidHabitat);
868
	}
869

    
870
	/**
871
	 * Returns the "habitat & ecology" feature. This feature only applies
872
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
873
	 * The "habitat & ecology" feature generalizes all other possible features concerning
874
	 * habitat and ecology matters.
875
	 */
876
	public static final Feature HABITAT_ECOLOGY(){
877
		return getTermByUuid(uuidHabitatAndEcology);
878
	}
879

    
880
	/**
881
	 * Returns the "biology_ecology" feature. This feature only applies
882
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
883
	 * The "biology_ecology" feature generalizes all possible features concerning
884
	 * biological aspects of ecological matters.
885
	 *
886
	 * @see #ECOLOGY()
887
	 */
888
	public static final Feature BIOLOGY_ECOLOGY(){
889
		return getTermByUuid(uuidBiologyEcology);
890
	}
891

    
892
	/**
893
	 * Returns the "chromosome number" feature. This feature only applies
894
	 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
895
	 */
896
	public static final Feature CHROMOSOME_NUMBER(){
897
		return getTermByUuid(uuidChromosomeNumber);
898
	}
899

    
900
	/**
901
	 * Returns the "key" feature. This feature is the "upper" feature generalizing
902
	 * all features being used within an identification key.
903
	 */
904
	public static final Feature KEY(){
905
		return getTermByUuid(uuidKey);
906
	}
907

    
908
	/**
909
	 * Returns the "materials_examined" feature. This feature can only be described
910
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
911
	 * mentioning which material has been examined in order to accomplish
912
	 * the description. This feature applies only to
913
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
914
	 */
915
	public static final Feature MATERIALS_EXAMINED(){
916
		return getTermByUuid(uuidMaterialsExamined);
917
	}
918

    
919
	/**
920
	 * Returns the "materials_methods" feature. This feature can only be described
921
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
922
	 * mentioning which methods have been adopted to analyze the material in
923
	 * order to accomplish the description. This feature applies only to
924
	 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
925
	 */
926
	public static final Feature MATERIALS_METHODS(){
927
		return getTermByUuid(uuidMaterialsMethods);
928
	}
929

    
930
	/**
931
	 * Returns the "etymology" feature. This feature can only be described
932
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
933
	 * giving some information about the history of the taxon name. This feature applies only to
934
	 * {@link TaxonNameDescription taxon name descriptions}.
935
	 */
936
	public static final Feature ETYMOLOGY(){
937
		return getTermByUuid(uuidEtymology);
938
	}
939

    
940
	/**
941
	 * Returns the "diagnosis" feature. This feature can only be described
942
	 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}.
943
	 * This feature applies only to {@link SpecimenDescription specimen descriptions} or to
944
	 * {@link TaxonDescription taxon descriptions}.
945
	 */
946
	public static final Feature DIAGNOSIS(){
947
		return getTermByUuid(uuidDiagnosis);
948
	}
949

    
950
	/**
951
	 * Returns the "introduction" feature. This feature can only be described
952
	 * with {@link TextData text data}.
953
	 *
954
	 * @see	#isSupportsTextData()
955
	 */
956
	public static final Feature INTRODUCTION(){
957
		return getTermByUuid(uuidIntroduction);
958
	}
959

    
960
	/**
961
	 * Returns the "protologue" feature. This feature can only be described
962
	 * with {@link TextData text data} reproducing the content of the protologue
963
	 * (or some information about it) of the taxon name. This feature applies only to
964
	 * {@link TaxonNameDescription taxon name descriptions}.
965
	 *
966
	 * @see	#isSupportsTextData()
967
	 */
968
	public static final Feature PROTOLOGUE(){
969
		return getTermByUuid(uuidProtologue);
970
	}
971

    
972
	/**
973
	 * Returns the "common_name" feature. This feature allows to handle only
974
	 * {@link CommonTaxonName common names}.
975
	 *
976
	 * @see	#isSupportsCommonTaxonName()
977
	 */
978
	public static final Feature COMMON_NAME(){
979
		return getTermByUuid(uuidCommonName);
980
	}
981

    
982
	/**
983
	 * Returns the "phenology" feature. This feature can only be described
984
	 * with {@link CategoricalData categorical data} or eventually with {@link TextData text data}
985
	 * containing information time about recurring natural phenomena.
986
	 * This feature only applies to {@link TaxonDescription taxon descriptions}.<BR>
987
	 * The "phenology" feature generalizes all other possible features
988
	 * concerning time information about particular natural phenomena
989
	 * (such as "first flight of butterflies").
990
	 */
991
	public static final Feature PHENOLOGY(){
992
		return getTermByUuid(uuidPhenology);
993
	}
994

    
995
	/**
996
	 * Returns the "occurrence" feature.
997
	 */
998
	public static final Feature OCCURRENCE(){
999
		return getTermByUuid(uuidOccurrence);
1000
	}
1001

    
1002
	/**
1003
	 * Returns the "anatomy" feature.
1004
	 */
1005
	public static final Feature ANATOMY(){
1006
		return getTermByUuid(uuidAnatomy);
1007
	}
1008

    
1009
	/**
1010
	 * Returns the "hostplant" feature.
1011
	 */
1012
	public static final Feature HOSTPLANT(){
1013
		return getTermByUuid(uuidHostPlant);
1014
	}
1015

    
1016
	/**
1017
	 * Returns the "pathogen agent" feature.
1018
	 */
1019
	public static final Feature PATHOGEN_AGENT(){
1020
		return getTermByUuid(uuidPathogenAgent);
1021
	}
1022

    
1023
	/**
1024
	 * Returns the "citation" feature. This feature can only be described
1025
	 * with {@link TextData text data}.
1026
	 *
1027
	 * @see	#isSupportsTextData()
1028
	 */
1029
	public static final Feature CITATION(){
1030
		return getTermByUuid(uuidCitation);
1031
	}
1032

    
1033
	/**
1034
	 * Returns the "additional_publication" feature. This feature can only be
1035
	 * described with {@link TextData text data} with information about a
1036
	 * publication where a {@link TaxonName taxon name} has also been published
1037
	 * but which is not the {@link TaxonName#getNomenclaturalReference() nomenclatural reference}.
1038
	 * This feature applies only to {@link TaxonNameDescription taxon name descriptions}.
1039
	 *
1040
	 * @see	#isSupportsTextData()
1041
	 */
1042
	public static final Feature ADDITIONAL_PUBLICATION(){
1043
		return getTermByUuid(uuidAdditionalPublication);
1044
	}
1045

    
1046
	/**
1047
	 * Returns the "uses" feature. This feature only applies
1048
	 * to {@link TaxonDescription taxon descriptions}.<BR>
1049
	 * The "uses" feature generalizes all other possible features concerning
1050
	 * particular uses (for instance "industrial use of seeds").
1051
	 */
1052
	public static final Feature USES(){
1053
		return getTermByUuid(uuidUses);
1054
	}
1055

    
1056
	public static final Feature USERECORD(){
1057
		return getTermByUuid(uuidUseRecord);
1058
	}
1059

    
1060
    /**
1061
     * Returns the "notes" feature. Used for
1062
     * taxonomic notes.
1063
     */
1064
    public static final Feature NOTES(){
1065
        return getTermByUuid(uuidNotes);
1066
    }
1067

    
1068
	/**
1069
	 * Returns the "conservation" feature. This feature only applies
1070
	 * to {@link SpecimenDescription specimen descriptions} and generalizes
1071
	 * methods and conditions for the conservation of {@link Specimen specimens}.<BR>
1072
	 */
1073
	public static final Feature CONSERVATION(){
1074
		return getTermByUuid(uuidConservation);
1075
	}
1076

    
1077
	/**
1078
	 * Returns the "cultivation" feature.
1079
	 */
1080
	public static final Feature CULTIVATION(){
1081
		return getTermByUuid(uuidCultivation);
1082
	}
1083

    
1084
	/**
1085
	 * Returns the "image" feature.
1086
	 */
1087
	public static final Feature IMAGE(){
1088
		return getTermByUuid(uuidImage);
1089
	}
1090

    
1091
	/**
1092
	 * Returns the "individuals association" feature.
1093
	 */
1094
	public static final Feature INDIVIDUALS_ASSOCIATION(){
1095
		Feature individuals_association =  getTermByUuid(uuidIndividualsAssociation);
1096
		Set<Feature> generalizationOf = new HashSet<>();
1097
		generalizationOf.add(SPECIMEN());
1098
		generalizationOf.add(OBSERVATION());
1099
		individuals_association.setGeneralizationOf(generalizationOf);
1100
		return individuals_association;
1101

    
1102
	}
1103

    
1104
	public static final Feature SPECIMEN(){
1105
		return getTermByUuid(uuidSpecimen);
1106
	}
1107

    
1108
	public static final Feature OBSERVATION(){
1109
		return getTermByUuid(uuidObservation);
1110
	}
1111

    
1112
	/**
1113
	 * The status of a taxon. Usually the status should be determined within a {@link Distribution distribution}.
1114
	 * If this is not possible for some reason (e.g. the area is not well defined) the status feature
1115
	 * may be used.
1116
	 * @return
1117
	 */
1118
	public static final Feature STATUS(){
1119
		return getTermByUuid(uuidStatus);
1120
	}
1121

    
1122
	public static final Feature SYSTEMATICS(){
1123
		return getTermByUuid(uuidSystematics);
1124
	}
1125

    
1126
	public static final Feature LIFEFORM(){
1127
        return getTermByUuid(uuidLifeform);
1128
    }
1129

    
1130
	public static final Feature FLOWERING_PERIOD(){
1131
	    return getTermByUuid(uuidFloweringPeriod);
1132
	}
1133

    
1134
    public static final Feature FRUITING_PERIOD(){
1135
        return getTermByUuid(uuidFruitingPeriod);
1136
    }
1137

    
1138
	public static final Feature ALTITUDE(){
1139
        return getTermByUuid(uuidAltitude);
1140
    }
1141
//
1142
//	/**
1143
//	 * Returns the "hybrid_parent" feature. This feature can only be used
1144
//	 * by {@link TaxonInteraction taxon interactions}.<BR>
1145
//	 * <P>
1146
//	 * Note: It must be distinguished between hybrid relationships as
1147
//	 * relevant nomenclatural relationships between {@link BotanicalName plant names}
1148
//	 * on the one side and the biological relation between two {@link Taxon taxa}
1149
//	 * as it is here the case on the other one.
1150
//	 *
1151
//	 * @see	#isSupportsTaxonInteraction()
1152
//	 * @see	HybridRelationshipType
1153
//	 */
1154
//	public static final Feature HYBRID_PARENT(){
1155
//		//TODO
1156
//		logger.warn("HYBRID_PARENT not yet implemented");
1157
//		return null;
1158
//	}
1159

    
1160
	@Override
1161
	protected void setDefaultTerms(TermVocabulary<Feature> termVocabulary) {
1162
		if (termMap == null){  //needed because there are multiple feature vocabularies
1163
			termMap = new HashMap<>();
1164
		}
1165
		for (Feature term : termVocabulary.getTerms()){
1166
			termMap.put(term.getUuid(), term);
1167
		}
1168
	}
1169

    
1170
//*********************************** CLONE *********************************************************/
1171

    
1172
    @Override
1173
    public Feature clone() {
1174
        Feature result = (Feature)super.clone();
1175

    
1176
        result.inverseRepresentations = new HashSet<Representation>();
1177
        for (Representation rep: this.inverseRepresentations){
1178
            result.addInverseRepresentation((Representation)rep.clone());
1179
        }
1180

    
1181
        //no changes to: symmetric, transitiv
1182
        return result;
1183
    }
1184

    
1185
}
(11-11/38)