2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.description
;
13 import java
.util
.HashMap
;
14 import java
.util
.HashSet
;
15 import java
.util
.List
;
18 import java
.util
.UUID
;
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
;
36 import org
.apache
.log4j
.Logger
;
37 import org
.hibernate
.annotations
.Cascade
;
38 import org
.hibernate
.annotations
.CascadeType
;
39 import org
.hibernate
.envers
.Audited
;
41 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
42 import eu
.etaxonomy
.cdm
.model
.name
.HybridRelationshipType
;
43 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
44 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
45 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
46 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTerm
;
47 import eu
.etaxonomy
.cdm
.model
.term
.DefinedTermBase
;
48 import eu
.etaxonomy
.cdm
.model
.term
.FeatureTree
;
49 import eu
.etaxonomy
.cdm
.model
.term
.Representation
;
50 import eu
.etaxonomy
.cdm
.model
.term
.TermType
;
51 import eu
.etaxonomy
.cdm
.model
.term
.TermVocabulary
;
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 TaxonName 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.
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.
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>
76 * This class corresponds to DescriptionsSectionType according to the SDD
80 * @since 08-Nov-2007 13:06:24
82 @XmlAccessorType(XmlAccessType
.PROPERTY
)
83 @XmlType(name
="Feature", factoryMethod
="NewInstance", propOrder
= {
89 "supportsQuantitativeData",
90 "supportsDistribution",
91 "supportsIndividualAssociation",
92 "supportsTaxonInteraction",
93 "supportsCommonTaxonName",
94 "supportsCategoricalData",
95 "recommendedModifierEnumeration",
96 "recommendedStatisticalMeasures",
97 "supportedCategoricalEnumerations",
98 "recommendedMeasurementUnits",
99 "inverseRepresentations"
101 @XmlRootElement(name
= "Feature")
103 //@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
104 //@Indexed(index = "eu.etaxonomy.cdm.model.term.DefinedTermBase")
106 public class Feature
extends DefinedTermBase
<Feature
> {
107 private static final long serialVersionUID
= 6754598791831848704L;
108 private static final Logger logger
= Logger
.getLogger(Feature
.class);
110 protected static Map
<UUID
, Feature
> termMap
= null;
112 private boolean supportsTextData
= true; //by default text data should be always supported
114 private boolean supportsQuantitativeData
;
116 private boolean supportsDistribution
;
118 private boolean supportsIndividualAssociation
;
120 private boolean supportsTaxonInteraction
;
122 private boolean supportsCategoricalData
;
124 private boolean supportsCommonTaxonName
;
126 /* for M:M see #4843 */
127 @ManyToMany(fetch
= FetchType
.LAZY
)
128 @JoinTable(name
="DefinedTermBase_RecommendedModifierEnumeration")
129 private final Set
<TermVocabulary
<DefinedTerm
>> recommendedModifierEnumeration
= new HashSet
<>();
131 @ManyToMany(fetch
= FetchType
.LAZY
)
132 @JoinTable(name
="DefinedTermBase_StatisticalMeasure")
133 private final Set
<StatisticalMeasure
> recommendedStatisticalMeasures
= new HashSet
<>();
135 /* for M:M see #4843 */
136 @ManyToMany(fetch
= FetchType
.LAZY
)
137 @JoinTable(name
="DefinedTermBase_SupportedCategoricalEnumeration")
138 private final Set
<TermVocabulary
<State
>> supportedCategoricalEnumerations
= new HashSet
<>();
141 @ManyToMany(fetch
= FetchType
.LAZY
)
142 @JoinTable(name
="DefinedTermBase_MeasurementUnit")
143 private final Set
<MeasurementUnit
> recommendedMeasurementUnits
= new HashSet
<>();
146 //copy from RelationshipTermBase
147 @XmlElementWrapper(name
= "InverseRepresentations")
148 @XmlElement(name
= "Representation")
149 @OneToMany(fetch
= FetchType
.LAZY
, orphanRemoval
=true)
150 @JoinTable(name
="DefinedTermBase_InverseRepresentation", //see also RelationshipTermBase.inverseRepresentations
151 joinColumns
=@JoinColumn(name
="DefinedTermBase_id")
152 // inverseJoinColumns
154 @Cascade({CascadeType
.SAVE_UPDATE
, CascadeType
.MERGE
, CascadeType
.DELETE
})
155 // @IndexedEmbedded(depth = 2)
156 private Set
<Representation
> inverseRepresentations
= new HashSet
<>();
158 private static final UUID uuidUnknown
= UUID
.fromString("910307f1-dc3c-452c-a6dd-af5ac7cd365c");
159 public static final UUID uuidDescription
= UUID
.fromString("9087cdcd-8b08-4082-a1de-34c9ba9fb493");
160 private static final UUID uuidDistribution
= UUID
.fromString("9fc9d10c-ba50-49ee-b174-ce83fc3f80c6");
161 private static final UUID uuidDistributionGeneral
= UUID
.fromString("fd8c64f0-6ea5-44b0-9f70-e95833d6076e");
162 private static final UUID uuidEcology
= UUID
.fromString("aa923827-d333-4cf5-9a5f-438ae0a4746b");
163 private static final UUID uuidHabitat
= UUID
.fromString("fb16929f-bc9c-456f-9d40-dec987b36438");
164 private static final UUID uuidHabitatAndEcology
= UUID
.fromString("9fdc4663-4d56-47d0-90b5-c0bf251bafbb");
165 private static final UUID uuidChromosomeNumber
= UUID
.fromString("6f677e98-d8d5-4bc5-80bf-affdb7e3945a");
167 private static final UUID uuidBiologyEcology
= UUID
.fromString("9832e24f-b670-43b4-ac7c-20a7261a1d8c");
168 private static final UUID uuidKey
= UUID
.fromString("a677f827-22b9-4205-bb37-11cb48dd9106");
169 private static final UUID uuidMaterialsExamined
= UUID
.fromString("7c0c7571-a864-47c1-891d-01f59000dae1");
170 private static final UUID uuidMaterialsMethods
= UUID
.fromString("1e87d9c3-0844-4a03-9686-773e2ccb3ab6");
171 private static final UUID uuidEtymology
= UUID
.fromString("dd653d48-355c-4aec-a4e7-724f6eb29f8d");
172 private static final UUID uuidDiagnosis
= UUID
.fromString("d43d8501-ceab-4caa-9e51-e87138528fac");
173 private static final UUID uuidProtologue
= UUID
.fromString("71b356c5-1e3f-4f5d-9b0f-c2cf8ae7779f");
174 public static final UUID uuidCommonName
= UUID
.fromString("fc810911-51f0-4a46-ab97-6562fe263ae5");
175 private static final UUID uuidPhenology
= UUID
.fromString("a7786d3e-7c58-4141-8416-346d4c80c4a2");
176 private static final UUID uuidOccurrence
= UUID
.fromString("5deff505-1a32-4817-9a74-50e6936fd630");
177 private static final UUID uuidCitation
= UUID
.fromString("99b2842f-9aa7-42fa-bd5f-7285311e0101");
178 private static final UUID uuidAdditionalPublication
= UUID
.fromString("2c355c16-cb04-4858-92bf-8da8d56dea95");
179 public static final UUID uuidUses
= UUID
.fromString("e5374d39-b210-47c7-bec1-bee05b5f1cb6");
180 private static final UUID uuidConservation
= UUID
.fromString("4518fc20-2492-47de-b345-777d2b83c9cf");
181 private static final UUID uuidCultivation
= UUID
.fromString("e28965b2-a367-48c5-b954-8afc8ac2c69b");
182 private static final UUID uuidIntroduction
= UUID
.fromString("e75255ca-8ff4-4905-baad-f842927fe1d3");
183 private static final UUID uuidDiscussion
= UUID
.fromString("d3c4cbb6-0025-4322-886b-cd0156753a25");
184 public static final UUID uuidImage
= UUID
.fromString("84193b2c-327f-4cce-90ef-c8da18fd5bb5");
185 private static final UUID uuidAnatomy
= UUID
.fromString("94213b2c-e67a-4d37-25ef-e8d316edfba1");
186 private static final UUID uuidHostPlant
= UUID
.fromString("6e9de1d5-05f0-40d5-8786-2fe30d0d894d");
187 private static final UUID uuidPathogenAgent
= UUID
.fromString("002d05f2-fd72-49f1-ba4d-196cf09240b5");
188 private static final UUID uuidIndividualsAssociation
= UUID
.fromString("e2308f37-ddc5-447d-b483-5e2171dd85fd");
189 public static final UUID uuidSpecimen
= UUID
.fromString("8200e050-d5fd-4cac-8a76-4b47afb13809");
190 private static final UUID uuidObservation
= UUID
.fromString("f59e747d-0b4f-4bf7-b69a-cbd50bc78595");
191 private static final UUID uuidStatus
= UUID
.fromString("86d40635-2a63-4ad6-be75-9faa4a6a57fb");
192 private static final UUID uuidSystematics
= UUID
.fromString("bd9aca17-cd0e-4418-a3a1-1a4b80dbc162");
193 private static final UUID uuidUseRecord
= UUID
.fromString("8125a59d-b4d5-4485-89ea-67306297b599");
194 private static final UUID uuidNotes
= UUID
.fromString("b5780b45-6439-4f3c-9818-d89d26d36eb2");
195 public static final UUID uuidLifeform
= UUID
.fromString("db9228d3-8bbf-4460-abfe-0b1326c82f8e");
198 /* ***************** CONSTRUCTOR AND FACTORY METHODS **********************************/
202 * Creates a new empty feature instance.
204 * @see #NewInstance(String, String, String)
206 public static Feature
NewInstance() {
207 return new Feature();
211 * Creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
212 * a label and a label abbreviation.
214 * @param description the string (in the default language) describing the
215 * new feature to be created
216 * @param label the string identifying the new feature to be created
217 * @param labelAbbrev the string identifying (in abbreviated form) the
218 * new feature to be created
219 * @see #readCsvLine(List, Language)
220 * @see #NewInstance()
222 public static Feature
NewInstance(String description
, String label
, String labelAbbrev
){
223 return new Feature(description
, label
, labelAbbrev
);
227 //for hibernate use only
229 protected Feature() {
230 super(TermType
.Feature
);
234 * Class constructor: creates a new feature instance with a description (in the {@link Language#DEFAULT() default language}),
235 * a label and a label abbreviation.
237 * @param term the string (in the default language) describing the
238 * new feature to be created
239 * @param label the string identifying the new feature to be created
240 * @param labelAbbrev the string identifying (in abbreviated form) the
241 * new feature to be created
244 protected Feature(String term
, String label
, String labelAbbrev
) {
245 super(TermType
.Feature
, term
, label
, labelAbbrev
);
248 /* *************************************************************************************/
251 public void resetTerms(){
257 * Returns the boolean value of the flag indicating whether <i>this</i>
258 * feature can be described with {@link QuantitativeData quantitative data} (true)
259 * or not (false). If this flag is set <i>this</i> feature can only apply to
260 * {@link TaxonDescription taxon descriptions} or {@link SpecimenDescription specimen descriptions}.
262 * @return the boolean value of the supportsQuantitativeData flag
264 @XmlElement(name
= "SupportsQuantitativeData")
265 public boolean isSupportsQuantitativeData() {
266 return supportsQuantitativeData
;
270 * @see #isSupportsQuantitativeData()
272 public void setSupportsQuantitativeData(boolean supportsQuantitativeData
) {
273 this.supportsQuantitativeData
= supportsQuantitativeData
;
277 * Returns the boolean value of the flag indicating whether <i>this</i>
278 * feature can be described with {@link TextData text data} (true)
281 * @return the boolean value of the supportsTextData flag
283 @XmlElement(name
= "SupportsTextData")
284 public boolean isSupportsTextData() {
285 return supportsTextData
;
289 * @see #isSupportsTextData()
291 public void setSupportsTextData(boolean supportsTextData
) {
292 this.supportsTextData
= supportsTextData
;
296 * Returns the boolean value of the flag indicating whether <i>this</i>
297 * feature can be described with {@link Distribution distribution} objects
298 * (true) or not (false). This flag is set if and only if <i>this</i> feature
299 * is the {@link #DISTRIBUTION() distribution feature}.
301 * @return the boolean value of the supportsDistribution flag
303 @XmlElement(name
= "SupportsDistribution")
304 public boolean isSupportsDistribution() {
305 return supportsDistribution
;
309 * @see #isSupportsDistribution()
311 public void setSupportsDistribution(boolean supportsDistribution
) {
312 this.supportsDistribution
= supportsDistribution
;
316 * Returns the boolean value of the flag indicating whether <i>this</i>
317 * feature can be described with {@link IndividualsAssociation individuals associations}
318 * (true) or not (false).
320 * @return the boolean value of the supportsIndividualAssociation flag
322 @XmlElement(name
= "SupportsIndividualAssociation")
323 public boolean isSupportsIndividualAssociation() {
324 return supportsIndividualAssociation
;
328 * @see #isSupportsIndividualAssociation()
330 public void setSupportsIndividualAssociation(
331 boolean supportsIndividualAssociation
) {
332 this.supportsIndividualAssociation
= supportsIndividualAssociation
;
336 * Returns the boolean value of the flag indicating whether <i>this</i>
337 * feature can be described with {@link TaxonInteraction taxon interactions}
338 * (true) or not (false).
340 * @return the boolean value of the supportsTaxonInteraction flag
342 @XmlElement(name
= "SupportsTaxonInteraction")
343 public boolean isSupportsTaxonInteraction() {
344 return supportsTaxonInteraction
;
348 * @see #isSupportsTaxonInteraction()
350 public void setSupportsTaxonInteraction(boolean supportsTaxonInteraction
) {
351 this.supportsTaxonInteraction
= supportsTaxonInteraction
;
355 * Returns the boolean value of the flag indicating whether <i>this</i>
356 * feature can be described with {@link CommonTaxonName common names}
357 * (true) or not (false). This flag is set if and only if <i>this</i> feature
358 * is the {@link #COMMON_NAME() common name feature}.
360 * @return the boolean value of the supportsCommonTaxonName flag
362 @XmlElement(name
= "SupportsCommonTaxonName")
363 public boolean isSupportsCommonTaxonName() {
364 return supportsCommonTaxonName
;
368 * @see #isSupportsTaxonInteraction()
370 public void setSupportsCommonTaxonName(boolean supportsCommonTaxonName
) {
371 this.supportsCommonTaxonName
= supportsCommonTaxonName
;
375 * Returns the boolean value of the flag indicating whether <i>this</i>
376 * feature can be described with {@link CategoricalData categorical data}
377 * (true) or not (false).
379 * @return the boolean value of the supportsCategoricalData flag
381 @XmlElement(name
= "SupportsCategoricalData")
382 public boolean isSupportsCategoricalData() {
383 return supportsCategoricalData
;
387 * @see #supportsCategoricalData()
389 public void setSupportsCategoricalData(boolean supportsCategoricalData
) {
390 this.supportsCategoricalData
= supportsCategoricalData
;
395 * Returns the set of {@link TermVocabulary term vocabularies} containing the
396 * {@link Modifier modifiers} recommended to be used for {@link DescriptionElementBase description elements}
397 * with <i>this</i> feature.
400 @XmlElementWrapper(name
= "RecommendedModifierEnumerations")
401 @XmlElement(name
= "RecommendedModifierEnumeration")
403 @XmlSchemaType(name
= "IDREF")
404 public Set
<TermVocabulary
<DefinedTerm
>> getRecommendedModifierEnumeration() {
405 return recommendedModifierEnumeration
;
409 * Adds a {@link TermVocabulary term vocabulary} (with {@link Modifier modifiers}) to the set of
410 * {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies} assigned
411 * to <i>this</i> feature.
413 * @param recommendedModifierEnumeration the term vocabulary to be added
414 * @see #getRecommendedModifierEnumeration()
416 public void addRecommendedModifierEnumeration(
417 TermVocabulary
<DefinedTerm
> recommendedModifierEnumeration
) {
418 this.recommendedModifierEnumeration
.add(recommendedModifierEnumeration
);
421 * Removes one element from the set of {@link #getRecommendedModifierEnumeration() recommended modifier vocabularies}
422 * assigned to <i>this</i> feature.
424 * @param recommendedModifierEnumeration the term vocabulary which should be removed
425 * @see #getRecommendedModifierEnumeration()
426 * @see #addRecommendedModifierEnumeration(TermVocabulary)
428 public void removeRecommendedModifierEnumeration(
429 TermVocabulary
<DefinedTerm
> recommendedModifierEnumeration
) {
430 this.recommendedModifierEnumeration
.remove(recommendedModifierEnumeration
);
434 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
435 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
437 @XmlElementWrapper(name
= "RecommendedStatisticalMeasures")
438 @XmlElement(name
= "RecommendedStatisticalMeasure")
440 @XmlSchemaType(name
= "IDREF")
441 public Set
<StatisticalMeasure
> getRecommendedStatisticalMeasures() {
442 return recommendedStatisticalMeasures
;
446 * Adds a {@link StatisticalMeasure statistical measure} to the set of
447 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
448 * to <i>this</i> feature.
450 * @param recommendedStatisticalMeasure the statistical measure to be added
451 * @see #getRecommendedStatisticalMeasures()
453 public void addRecommendedStatisticalMeasure(
454 StatisticalMeasure recommendedStatisticalMeasure
) {
455 this.recommendedStatisticalMeasures
.add(recommendedStatisticalMeasure
);
458 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
459 * assigned to <i>this</i> feature.
461 * @param recommendedStatisticalMeasure the statistical measure which should be removed
462 * @see #getRecommendedStatisticalMeasures()
463 * @see #addRecommendedStatisticalMeasure(StatisticalMeasure)
465 public void removeRecommendedStatisticalMeasure(
466 StatisticalMeasure recommendedStatisticalMeasure
) {
467 this.recommendedStatisticalMeasures
.remove(recommendedStatisticalMeasure
);
471 * Returns the set of {@link StatisticalMeasure statistical measures} recommended to be used
472 * in case of {@link QuantitativeData quantitative data} with <i>this</i> feature.
474 @XmlElementWrapper(name
= "RecommendedMeasurementUnits")
475 @XmlElement(name
= "RecommendedMeasurementUnit")
477 @XmlSchemaType(name
= "IDREF")
478 public Set
<MeasurementUnit
> getRecommendedMeasurementUnits() {
479 return recommendedMeasurementUnits
;
483 * Adds a {@link StatisticalMeasure statistical measure} to the set of
484 * {@link #getRecommendedStatisticalMeasures() recommended statistical measures} assigned
485 * to <i>this</i> feature.
487 * @param recommendedStatisticalMeasure the statistical measure to be added
488 * @see #getRecommendedStatisticalMeasures()
490 public void addRecommendedMeasurementUnit(
491 MeasurementUnit recommendedMeasurementUnit
) {
492 this.recommendedMeasurementUnits
.add(recommendedMeasurementUnit
);
495 * Removes one element from the set of {@link #getRecommendedStatisticalMeasures() recommended statistical measures}
496 * assigned to <i>this</i> feature.
498 * @param recommendedStatisticalMeasure the statistical measure which should be removed
499 * @see #getRecommendedStatisticalMeasures()
500 * @see #addRecommendedStatisticalMeasure(StatisticalMeasure)
502 public void removeRecommendedMeasurementUnit(
503 MeasurementUnit recommendedMeasurementUnit
) {
504 this.recommendedMeasurementUnits
.remove(recommendedMeasurementUnit
);
508 * Returns the set of {@link TermVocabulary term vocabularies} containing the list of
509 * possible {@link State states} to be used in {@link CategoricalData categorical data}
510 * with <i>this</i> feature.
513 @XmlElementWrapper(name
= "SupportedCategoricalEnumerations")
514 @XmlElement(name
= "SupportedCategoricalEnumeration")
516 @XmlSchemaType(name
= "IDREF")
517 public Set
<TermVocabulary
<State
>> getSupportedCategoricalEnumerations() {
518 return supportedCategoricalEnumerations
;
522 * Adds a {@link TermVocabulary term vocabulary} to the set of
523 * {@link #getSupportedCategoricalEnumerations() supported state vocabularies} assigned
524 * to <i>this</i> feature.
526 * @param supportedCategoricalEnumeration the term vocabulary which should be removed
527 * @see #getSupportedCategoricalEnumerations()
529 public void addSupportedCategoricalEnumeration(
530 TermVocabulary
<State
> supportedCategoricalEnumeration
) {
531 this.supportedCategoricalEnumerations
.add(supportedCategoricalEnumeration
);
534 * Removes one element from the set of {@link #getSupportedCategoricalEnumerations() supported state vocabularies}
535 * assigned to <i>this</i> feature.
537 * @param supportedCategoricalEnumeration the term vocabulary which should be removed
538 * @see #getSupportedCategoricalEnumerations()
539 * @see #addSupportedCategoricalEnumeration(TermVocabulary)
541 public void removeSupportedCategoricalEnumeration(
542 TermVocabulary
<State
> supportedCategoricalEnumeration
) {
543 this.supportedCategoricalEnumerations
.remove(supportedCategoricalEnumeration
);
546 @XmlElement(name
= "KindOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
548 @XmlSchemaType(name
= "IDREF")
550 public Feature
getKindOf(){
551 return super.getKindOf();
555 public void setKindOf(Feature kindOf
){
556 super.setKindOf(kindOf
);
560 @XmlElement(name
= "PartOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
562 @XmlSchemaType(name
= "IDREF")
563 public Feature
getPartOf(){
564 return super.getPartOf();
568 public void setPartOf(Feature partOf
){
569 super.setPartOf(partOf
);
573 @XmlElementWrapper(name
= "Generalizations", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
574 @XmlElement(name
= "GeneralizationOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
576 @XmlSchemaType(name
= "IDREF")
577 public Set
<Feature
> getGeneralizationOf(){
578 return super.getGeneralizationOf();
582 protected void setGeneralizationOf(Set
<Feature
> value
){
583 super.setGeneralizationOf(value
);
587 @XmlElementWrapper(name
= "Includes", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
588 @XmlElement(name
= "Include", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
590 @XmlSchemaType(name
= "IDREF")
591 public Set
<Feature
> getIncludes(){
592 return super.getIncludes();
596 protected void setIncludes(Set
<Feature
> includes
) {
597 super.setIncludes(includes
);
600 // ***************** Invers Label *****************************************/
602 public Set
<Representation
> getInverseRepresentations() {
603 return inverseRepresentations
;
605 public void addInverseRepresentation(Representation inverseRepresentation
) {
606 this.inverseRepresentations
.add(inverseRepresentation
);
608 public void removeInverseRepresentation(Representation inverseRepresentation
) {
609 this.inverseRepresentations
.remove(inverseRepresentation
);
612 * Inverse representation convenience methods similar to TermBase.xxx
613 * @see eu.etaxonomy.cdm.model.term.TermBase#getLabel()
616 public String
getInverseLabel() {
617 if(getInverseLabel(Language
.DEFAULT()) != null){
618 return this.getInverseRepresentation(Language
.DEFAULT()).getLabel();
620 for (Representation r
: inverseRepresentations
){
624 return super.getUuid().toString();
626 public String
getInverseLabel(Language lang
) {
627 Representation r
= this.getInverseRepresentation(lang
);
634 public Representation
getInverseRepresentation(Language lang
) {
635 Representation result
= null;
636 for (Representation repr
: this.getInverseRepresentations()){
637 if (lang
.equals(repr
.getLanguage())){
643 // ****************** END INVERS REPRESENTATION **************************/
646 * Creates and returns a new feature instance on the basis of a given string
647 * list (containing an UUID, an URI, a label and a description) and a given
648 * {@link Language language} to be associated with the description. Furthermore
649 * the flags concerning the supported subclasses of {@link DescriptionElementBase description elements}
650 * are set according to a particular string belonging to the given
652 * This method overrides the readCsvLine method from {@link DefinedTermBase#readCsvLine(List, Language) DefinedTermBase}.
654 * @param csvLine the string list with elementary information for attributes
655 * @param lang the language in which the description has been formulated
656 * @see #NewInstance(String, String, String)
659 public Feature
readCsvLine(Class
<Feature
> termClass
, List
<String
> csvLine
, TermType termType
,
660 Map
<UUID
,DefinedTermBase
> terms
, boolean abbrevAsId
) {
661 Feature newInstance
= super.readCsvLine(termClass
, csvLine
, termType
, terms
, abbrevAsId
);
662 String text
= csvLine
.get(4);
663 if (text
!= null && text
.length() >= 6){
664 if ("1".equals(text
.substring(0, 1))){newInstance
.setSupportsTextData(true);}
665 if ("1".equals(text
.substring(1, 2))){newInstance
.setSupportsQuantitativeData(true);}
666 if ("1".equals(text
.substring(2, 3))){newInstance
.setSupportsDistribution(true);}
667 if ("1".equals(text
.substring(3, 4))){newInstance
.setSupportsIndividualAssociation(true);}
668 if ("1".equals(text
.substring(4, 5))){newInstance
.setSupportsTaxonInteraction(true);}
669 if ("1".equals(text
.substring(5, 6))){newInstance
.setSupportsCommonTaxonName(true);}
670 if (text
.length() > 6 && "1".equals(text
.substring(6, 7))){newInstance
.setSupportsCategoricalData(true);}
671 //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
672 newInstance
.getRepresentation(Language
.DEFAULT()).setAbbreviatedLabel(null);
677 //******************************* STATIC METHODS *****************************************
679 protected static Feature
getTermByUuid(UUID uuid
){
680 if (termMap
== null || termMap
.isEmpty()){
681 return getTermByClassAndUUID(Feature
.class, uuid
);
683 return termMap
.get(uuid
);
688 * Returns the "unknown" feature. This feature allows to store values of
689 * {@link DescriptionElementBase description elements} even if it is momentarily
690 * not known what they mean.
692 public static final Feature
UNKNOWN(){
693 return getTermByUuid(uuidUnknown
);
697 * Returns the "description" feature. This feature allows to handle global
698 * {@link DescriptionElementBase description elements} for a global {@link DescriptionBase description}.<BR>
699 * The "description" feature is the highest level feature.
701 public static final Feature
DESCRIPTION(){
702 return getTermByUuid(uuidDescription
);
706 * Returns the "distribution" feature. This feature allows to handle only
707 * {@link Distribution distributions}.
709 * @see #isSupportsDistribution()
711 public static final Feature
DISTRIBUTION(){
712 return getTermByUuid(uuidDistribution
);
716 * Returns the feature for general text-based
719 public static final Feature
DISTRIBUTION_GENERAL(){
720 return getTermByUuid(uuidDistributionGeneral
);
724 * Returns the "discussion" feature. This feature can only be described
725 * with {@link TextData text data}.
727 * @see #isSupportsTextData()
729 public static final Feature
DISCUSSION(){
730 return getTermByUuid(uuidDiscussion
);
734 * Returns the "ecology" feature. This feature only applies
735 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
736 * The "ecology" feature generalizes all other possible features concerning
737 * ecological matters.
739 public static final Feature
ECOLOGY(){
740 return getTermByUuid(uuidEcology
);
744 * Returns the "habitat" feature. This feature only applies
745 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
746 * The "habitat" feature generalizes all other possible features concerning
749 public static final Feature
HABITAT(){
750 return getTermByUuid(uuidHabitat
);
755 * Returns the "habitat & ecology" feature. This feature only applies
756 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
757 * The "habitat & ecology" feature generalizes all other possible features concerning
758 * habitat and ecology matters.
760 public static final Feature
HABITAT_ECOLOGY(){
761 return getTermByUuid(uuidHabitatAndEcology
);
765 * Returns the "biology_ecology" feature. This feature only applies
766 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
767 * The "biology_ecology" feature generalizes all possible features concerning
768 * biological aspects of ecological matters.
772 public static final Feature
BIOLOGY_ECOLOGY(){
773 return getTermByUuid(uuidBiologyEcology
);
777 * Returns the "chromosome number" feature. This feature only applies
778 * to {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.<BR>
780 public static final Feature
CHROMOSOME_NUMBER(){
781 return getTermByUuid(uuidChromosomeNumber
);
786 * Returns the "key" feature. This feature is the "upper" feature generalizing
787 * all features being used within an identification key.
789 public static final Feature
KEY(){
790 return getTermByUuid(uuidKey
);
795 * Returns the "materials_examined" feature. This feature can only be described
796 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
797 * mentioning which material has been examined in order to accomplish
798 * the description. This feature applies only to
799 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
801 public static final Feature
MATERIALS_EXAMINED(){
802 return getTermByUuid(uuidMaterialsExamined
);
806 * Returns the "materials_methods" feature. This feature can only be described
807 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
808 * mentioning which methods have been adopted to analyze the material in
809 * order to accomplish the description. This feature applies only to
810 * {@link SpecimenDescription specimen descriptions} or to {@link TaxonDescription taxon descriptions}.
812 public static final Feature
MATERIALS_METHODS(){
813 return getTermByUuid(uuidMaterialsMethods
);
817 * Returns the "etymology" feature. This feature can only be described
818 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}
819 * giving some information about the history of the taxon name. This feature applies only to
820 * {@link TaxonNameDescription taxon name descriptions}.
822 public static final Feature
ETYMOLOGY(){
823 return getTermByUuid(uuidEtymology
);
827 * Returns the "diagnosis" feature. This feature can only be described
828 * with {@link TextData text data} or eventually with {@link CategoricalData categorical data}.
829 * This feature applies only to {@link SpecimenDescription specimen descriptions} or to
830 * {@link TaxonDescription taxon descriptions}.
832 public static final Feature
DIAGNOSIS(){
833 return getTermByUuid(uuidDiagnosis
);
838 * Returns the "introduction" feature. This feature can only be described
839 * with {@link TextData text data}.
841 * @see #isSupportsTextData()
843 public static final Feature
INTRODUCTION(){
844 return getTermByUuid(uuidIntroduction
);
848 * Returns the "protologue" feature. This feature can only be described
849 * with {@link TextData text data} reproducing the content of the protologue
850 * (or some information about it) of the taxon name. This feature applies only to
851 * {@link TaxonNameDescription taxon name descriptions}.
853 * @see #isSupportsTextData()
855 public static final Feature
PROTOLOGUE(){
856 return getTermByUuid(uuidProtologue
);
860 * Returns the "common_name" feature. This feature allows to handle only
861 * {@link CommonTaxonName common names}.
863 * @see #isSupportsCommonTaxonName()
865 public static final Feature
COMMON_NAME(){
866 return getTermByUuid(uuidCommonName
);
870 * Returns the "phenology" feature. This feature can only be described
871 * with {@link CategoricalData categorical data} or eventually with {@link TextData text data}
872 * containing information time about recurring natural phenomena.
873 * This feature only applies to {@link TaxonDescription taxon descriptions}.<BR>
874 * The "phenology" feature generalizes all other possible features
875 * concerning time information about particular natural phenomena
876 * (such as "first flight of butterflies").
878 public static final Feature
PHENOLOGY(){
879 return getTermByUuid(uuidPhenology
);
883 * Returns the "occurrence" feature.
885 public static final Feature
OCCURRENCE(){
886 return getTermByUuid(uuidOccurrence
);
890 * Returns the "anatomy" feature.
892 public static final Feature
ANATOMY(){
893 return getTermByUuid(uuidAnatomy
);
896 * Returns the "hostplant" feature.
898 public static final Feature
HOSTPLANT(){
899 return getTermByUuid(uuidHostPlant
);
902 * Returns the "pathogen agent" feature.
904 public static final Feature
PATHOGEN_AGENT(){
905 return getTermByUuid(uuidPathogenAgent
);
909 * Returns the "citation" feature. This feature can only be described
910 * with {@link TextData text data}.
912 * @see #isSupportsTextData()
914 public static final Feature
CITATION(){
915 return getTermByUuid(uuidCitation
);
919 * Returns the "additional_publication" feature. This feature can only be
920 * described with {@link TextData text data} with information about a
921 * publication where a {@link TaxonName taxon name} has also been published
922 * but which is not the {@link TaxonName#getNomenclaturalReference() nomenclatural reference}.
923 * This feature applies only to {@link TaxonNameDescription taxon name descriptions}.
925 * @see #isSupportsTextData()
927 public static final Feature
ADDITIONAL_PUBLICATION(){
928 return getTermByUuid(uuidAdditionalPublication
);
933 * Returns the "uses" feature. This feature only applies
934 * to {@link TaxonDescription taxon descriptions}.<BR>
935 * The "uses" feature generalizes all other possible features concerning
936 * particular uses (for instance "industrial use of seeds").
938 public static final Feature
USES(){
939 return getTermByUuid(uuidUses
);
942 public static final Feature
USERECORD(){
943 return getTermByUuid(uuidUseRecord
);
947 * Returns the "notes" feature. Used for
950 public static final Feature
NOTES(){
951 return getTermByUuid(uuidNotes
);
955 * Returns the "conservation" feature. This feature only applies
956 * to {@link SpecimenDescription specimen descriptions} and generalizes
957 * methods and conditions for the conservation of {@link Specimen specimens}.<BR>
959 public static final Feature
CONSERVATION(){
960 return getTermByUuid(uuidConservation
);
965 * Returns the "cultivation" feature.
967 public static final Feature
CULTIVATION(){
968 return getTermByUuid(uuidCultivation
);
973 * Returns the "image" feature.
975 public static final Feature
IMAGE(){
976 return getTermByUuid(uuidImage
);
980 * Returns the "individuals association" feature.
982 public static final Feature
INDIVIDUALS_ASSOCIATION(){
983 Feature individuals_association
= getTermByUuid(uuidIndividualsAssociation
);
984 Set
<Feature
> generalizationOf
= new HashSet
<>();
985 generalizationOf
.add(SPECIMEN());
986 generalizationOf
.add(OBSERVATION());
987 individuals_association
.setGeneralizationOf(generalizationOf
);
988 return individuals_association
;
992 public static final Feature
SPECIMEN(){
993 return getTermByUuid(uuidSpecimen
);
996 public static final Feature
OBSERVATION(){
997 return getTermByUuid(uuidObservation
);
1001 * The status of a taxon. Usually the status should be determined within a {@link Distribution distribution}.
1002 * If this is not possible for some reason (e.g. the area is not well defined) the status feature
1006 public static final Feature
STATUS(){
1007 return getTermByUuid(uuidStatus
);
1010 public static final Feature
SYSTEMATICS(){
1011 return getTermByUuid(uuidSystematics
);
1014 public static final Feature
LIFEFORM(){
1015 return getTermByUuid(uuidLifeform
);
1019 * Returns the "hybrid_parent" feature. This feature can only be used
1020 * by {@link TaxonInteraction taxon interactions}.<BR>
1022 * Note: It must be distinguished between hybrid relationships as
1023 * relevant nomenclatural relationships between {@link BotanicalName plant names}
1024 * on the one side and the biological relation between two {@link Taxon taxa}
1025 * as it is here the case on the other one.
1027 * @see #isSupportsTaxonInteraction()
1028 * @see HybridRelationshipType
1030 public static final Feature
HYBRID_PARENT(){
1032 logger
.warn("HYBRID_PARENT not yet implemented");
1037 protected void setDefaultTerms(TermVocabulary
<Feature
> termVocabulary
) {
1038 if (termMap
== null){ //needed because there are multiple feature vocabularies
1039 termMap
= new HashMap
<UUID
, Feature
>();
1041 for (Feature term
: termVocabulary
.getTerms()){
1042 termMap
.put(term
.getUuid(), term
);
1046 //*********************************** CLONE *********************************************************/
1049 public Object
clone() {
1050 Feature result
= (Feature
)super.clone();
1052 result
.inverseRepresentations
= new HashSet
<Representation
>();
1053 for (Representation rep
: this.inverseRepresentations
){
1054 result
.addInverseRepresentation((Representation
)rep
.clone());
1057 //no changes to: symmetric, transitiv