Project

General

Profile

Revision 951c829f

ID951c829f32b1b9c809b530d3545481eb39a1ade9
Parent 1c313fd1
Child 3de5dbd5

Added by Andreas Müller about 1 year ago

ref #6794 add TermRelation and rename FeatureNode -> TermTreeNode

View differences:

cdmlib-cache/src/main/resources/eu/etaxonomy/cdm/mappings/hibernate.cfg.xml
103 103
      <mapping class="eu.etaxonomy.cdm.model.description.Distribution"/>
104 104
      <mapping class="eu.etaxonomy.cdm.model.description.Feature"/>
105 105
      <mapping class="eu.etaxonomy.cdm.model.description.Character"/>
106
      <mapping class="eu.etaxonomy.cdm.model.term.FeatureNode"/>
107
      <mapping class="eu.etaxonomy.cdm.model.term.FeatureTree"/>
108 106
      <mapping class="eu.etaxonomy.cdm.model.description.KeyStatement"/>
109 107
      <mapping class="eu.etaxonomy.cdm.model.description.MediaKey"/>
110 108
      <mapping class="eu.etaxonomy.cdm.model.description.IndividualsAssociation"/>
......
211 209
      <!-- Term Package -->
212 210
      <mapping class="eu.etaxonomy.cdm.model.term.DefinedTerm"/>
213 211
      <mapping class="eu.etaxonomy.cdm.model.term.DefinedTermBase"/>
212
      <mapping class="eu.etaxonomy.cdm.model.term.FeatureTree"/>
214 213
      <mapping class="eu.etaxonomy.cdm.model.term.OrderedTerm"/>
215 214
      <mapping class="eu.etaxonomy.cdm.model.term.OrderedTermBase"/>
216 215
      <mapping class="eu.etaxonomy.cdm.model.term.OrderedTermVocabulary"/>
217 216
      <mapping class="eu.etaxonomy.cdm.model.term.Representation"/>
217
      <mapping class="eu.etaxonomy.cdm.model.term.TermRelationshipType"/>
218
      <mapping class="eu.etaxonomy.cdm.model.term.TermTreeNode"/>
218 219
      <mapping class="eu.etaxonomy.cdm.model.term.TermVocabulary"/>
219 220
      
220 221
      <!-- Validation Package -->
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/descriptive/owl/in/OwlImportUtil.java
1
/**
2
* Copyright (C) 2019 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
package eu.etaxonomy.cdm.io.descriptive.owl.in;
10

  
11
import java.net.URI;
12
import java.util.Collections;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.UUID;
17

  
18
import com.hp.hpl.jena.rdf.model.Model;
19
import com.hp.hpl.jena.rdf.model.Resource;
20
import com.hp.hpl.jena.rdf.model.Statement;
21

  
22
import eu.etaxonomy.cdm.api.application.ICdmRepository;
23
import eu.etaxonomy.cdm.common.CdmUtils;
24
import eu.etaxonomy.cdm.io.descriptive.owl.OwlUtil;
25
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
26
import eu.etaxonomy.cdm.model.common.Language;
27
import eu.etaxonomy.cdm.model.description.Character;
28
import eu.etaxonomy.cdm.model.description.Feature;
29
import eu.etaxonomy.cdm.model.description.MeasurementUnit;
30
import eu.etaxonomy.cdm.model.description.State;
31
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
32
import eu.etaxonomy.cdm.model.media.Media;
33
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
34
import eu.etaxonomy.cdm.model.reference.Reference;
35
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
36
import eu.etaxonomy.cdm.model.term.DefinedTerm;
37
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
38
import eu.etaxonomy.cdm.model.term.FeatureNode;
39
import eu.etaxonomy.cdm.model.term.Representation;
40
import eu.etaxonomy.cdm.model.term.TermType;
41
import eu.etaxonomy.cdm.model.term.TermVocabulary;
42

  
43
/**
44
 * @author pplitzner
45
 * @since May 26, 2019
46
 *
47
 */
48
public class OwlImportUtil {
49

  
50
    static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(OwlImportUtil.class);
51

  
52
    private static void addFeatureProperties(Feature feature, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
53
        if(termResource.hasProperty(OwlUtil.propFeatureIsCategorical)){
54
            feature.setSupportsCategoricalData(termResource.getProperty(OwlUtil.propFeatureIsCategorical).getBoolean());
55
        }
56
        if(termResource.hasProperty(OwlUtil.propFeatureIsQuantitative)){
57
            feature.setSupportsQuantitativeData(termResource.getProperty(OwlUtil.propFeatureIsQuantitative).getBoolean());
58
        }
59
        // import measurement units
60
        Set<MeasurementUnit> measurementUnits = new HashSet<>();
61
        List<Statement> measurementUnitStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedMeasurementUnit).toList();
62
        for (Statement statement : measurementUnitStatements) {
63
            Resource measurementUnitResource = model.createResource(statement.getObject().toString());
64
            MeasurementUnit measurementUnit = findTerm(MeasurementUnit.class, measurementUnitResource, repo, model, state);
65
            if(measurementUnit==null){
66
                measurementUnit = MeasurementUnit.NewInstance();
67
                addTermProperties(measurementUnit, measurementUnitResource, repo, model, state);
68
            }
69
            measurementUnits.add(measurementUnit);
70
        }
71
        measurementUnits.forEach(unit->feature.addRecommendedMeasurementUnit(unit));
72
        // import modifier TODO: create entire vocabulary if it cannot be found
73
        Set<TermVocabulary<DefinedTerm>> modifierVocs = new HashSet<>();
74
        List<Statement> modifierEnumStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedModifierEnumeration).toList();
75
        for (Statement statement : modifierEnumStatements) {
76
            Resource modifierEnumResource = model.createResource(statement.getObject().toString());
77
            TermVocabulary modifierVoc = findVocabulary(modifierEnumResource, repo, model, state);
78
            if(modifierVoc!=null){
79
                modifierVocs.add(modifierVoc);
80
            }
81
        }
82
        modifierVocs.forEach(modiferVoc->feature.addRecommendedModifierEnumeration(modiferVoc));
83
        // import statistical measures
84
        Set<StatisticalMeasure> statisticalMeasures = new HashSet<>();
85
        List<Statement> statisticalMeasureStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedStatisticalMeasure).toList();
86
        for (Statement statement : statisticalMeasureStatements) {
87
            Resource statisticalMeasureResource = model.createResource(statement.getObject().toString());
88
            StatisticalMeasure statisticalMeasure = findTerm(StatisticalMeasure.class, statisticalMeasureResource, repo, model, state);
89
            if(statisticalMeasure==null){
90
                statisticalMeasure = StatisticalMeasure.NewInstance();
91
                addTermProperties(statisticalMeasure, statisticalMeasureResource, repo, model, state);
92
            }
93
            statisticalMeasures.add(statisticalMeasure);
94
        }
95
        statisticalMeasures.forEach(statisticalMeasure->feature.addRecommendedStatisticalMeasure(statisticalMeasure));
96
        // import categorical enums TODO: create entire vocabulary if it cannot be found
97
        Set<TermVocabulary<State>> stateVocs = new HashSet<>();
98
        List<Statement> stateVocStatements = termResource.listProperties(OwlUtil.propFeatureHasSupportedCategoricalEnumeration).toList();
99
        for (Statement statement : stateVocStatements) {
100
            Resource stateVocResource = model.createResource(statement.getObject().toString());
101
            TermVocabulary stateVoc = findVocabulary(stateVocResource, repo, model, state);
102
            if(stateVoc!=null){
103
                stateVocs.add(stateVoc);
104
            }
105
        }
106
        stateVocs.forEach(stateVoc->feature.addSupportedCategoricalEnumeration(stateVoc));
107
    }
108

  
109
    private static void addCharacterProperties(Character character, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
110
        addFeatureProperties(character, termResource, repo, model, state);
111
        // TODO import/export of complete term tree of structures and properties belonging to a character is necessary
112
        // import structure
113
        Statement structureStatement = termResource.getProperty(OwlUtil.propCharacterHasStructure);
114
        Resource structureResource = model.createResource(structureStatement.getObject().toString());
115
        FeatureNode structureNode = findNode(structureResource, repo, model, state);
116
        if(structureNode!=null){
117
            character.setStructure(structureNode);
118
        }
119
        // import property
120
        Statement propertyStatement = termResource.getProperty(OwlUtil.propCharacterHasProperty);
121
        Resource propertyResource = model.createResource(propertyStatement.getObject().toString());
122
        FeatureNode propertyNode = findNode(propertyResource, repo, model, state);
123
        if(propertyNode!=null){
124
            character.setProperty(propertyNode);
125
        }
126
        // import structure modifier
127
        if(termResource.hasProperty(OwlUtil.propCharacterHasStructureModfier)){
128
            Statement structureModifierStatement = termResource.getProperty(OwlUtil.propCharacterHasStructureModfier);
129
            Resource structureModifierResource = model.createResource(structureModifierStatement.getObject().toString());
130
            DefinedTerm structureModifier = findTerm(DefinedTerm.class, structureModifierResource, repo, model, state);
131
            character.setStructureModifier(structureModifier);
132
        }
133
    }
134

  
135
    private static void addTermProperties(DefinedTermBase term, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
136
        term.setUuid(UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString()));
137

  
138
        // term URI
139
        String uriString = termResource.hasProperty(OwlUtil.propUri)?termResource.getProperty(OwlUtil.propUri).getString():null;
140
        if(CdmUtils.isNotBlank(uriString)){
141
            term.setUri(URI.create(uriString));
142
        }
143
        // symbol
144
        String symbolString = termResource.hasProperty(OwlUtil.propTermSymbol)?termResource.getProperty(OwlUtil.propTermSymbol).getString():null;
145
        if(CdmUtils.isNotBlank(symbolString)){
146
            term.setSymbol(symbolString);
147
        }
148
        // symbol2
149
        String symbol2String = termResource.hasProperty(OwlUtil.propTermSymbol2)?termResource.getProperty(OwlUtil.propTermSymbol2).getString():null;
150
        if(CdmUtils.isNotBlank(symbol2String)){
151
            term.setSymbol2(symbol2String);
152
        }
153
        // idInVocabulary
154
        String idInVocabularyString = termResource.hasProperty(OwlUtil.propTermIdInVocabulary)?termResource.getProperty(OwlUtil.propTermIdInVocabulary).getString():null;
155
        if(CdmUtils.isNotBlank(idInVocabularyString)){
156
            term.setIdInVocabulary(idInVocabularyString);
157
        }
158

  
159
        // import representations
160
        Set<Representation> representations = new HashSet<>();
161
        termResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->representations.add(OwlImportUtil.createRepresentation(repo, r, model)));
162
        if(representations.isEmpty()){
163
            logger.error("No representations found for term: "+termResource.getProperty(OwlUtil.propUuid));
164
        }
165
        representations.forEach(rep->term.addRepresentation(rep));
166

  
167
        // import sources
168
        Set<IdentifiableSource> sources = new HashSet<>();
169
        termResource.listProperties(OwlUtil.propTermHasSource).forEachRemaining(sourceStatement->sources.add(OwlImportUtil.createSource(sourceStatement, repo, model)));
170
        sources.forEach(source->term.addSource(source));
171

  
172
        // add import source
173
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(termResource.getURI());
174
        importSource.setCitation(state.getConfig().getSourceReference());
175
        term.addSource(importSource);
176
    }
177

  
178
    private static <T extends DefinedTermBase> T findTerm(Class<T> clazz, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
179
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
180
        List<T> terms = repo.getTermService().find(clazz, Collections.singleton(termUuid));
181
        if(!terms.isEmpty()){
182
            return terms.iterator().next();
183
        }
184
        return null;
185
    }
186

  
187
    private static TermVocabulary findVocabulary(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
188
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
189
        return repo.getVocabularyService().find(termUuid);
190
    }
191

  
192
    private static FeatureNode findNode(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
193
        UUID uuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
194
        return repo.getFeatureNodeService().find(uuid);
195
    }
196

  
197
    private static Reference findReference(Resource resource, ICdmRepository repo){
198
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
199
        return repo.getReferenceService().find(uuid);
200
    }
201

  
202
    static Media findMedia(Resource resource, ICdmRepository repo){
203
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
204
        return repo.getMediaService().find(uuid);
205
    }
206

  
207
    static Feature createFeature(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
208
        Feature feature = findTerm(Feature.class, termResource, repo, model, state);
209
        if(feature==null){
210
            feature = Feature.NewInstance();
211
            addFeatureProperties(feature, termResource, repo, model, state);
212
        }
213
        return feature;
214
    }
215

  
216
    private static Character createCharacter(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
217
        Character character = findTerm(Character.class, termResource, repo, model, state);
218
        if(character==null){
219
            character = Character.NewInstance();
220
            addCharacterProperties(character, termResource, repo, model, state);
221
        }
222
        return character;
223
    }
224

  
225
    static DefinedTermBase createTerm(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
226
        TermType termType = TermType.getByKey(termResource.getProperty(OwlUtil.propType).getString());
227
        DefinedTermBase term = null;
228
        // create new term
229
        if(termType.equals(TermType.Feature)){
230
            term = createFeature(termResource, repo, model, state);
231
        }
232
        else if(termType.equals(TermType.Character)){
233
            term = createCharacter(termResource, repo, model, state);
234
        }
235
        else{
236
            term = DefinedTerm.NewInstance(termType);
237
        }
238
        addTermProperties(term, termResource, repo, model, state);
239
        return term;
240
    }
241

  
242
    static IdentifiableSource createSource(Statement sourceStatement, ICdmRepository repo, Model model) {
243
        Resource sourceResource = model.createResource(sourceStatement.getObject().toString());
244

  
245
        String typeString = sourceResource.getProperty(OwlUtil.propSourceType).getString();
246
        IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.getByKey(typeString));
247

  
248
        if(sourceResource.hasProperty(OwlUtil.propSourceIdInSource)){
249
            String idInSource = sourceResource.getProperty(OwlUtil.propSourceIdInSource).getString();
250
            source.setIdInSource(idInSource);
251
        }
252

  
253
        // import citation
254
        List<Statement> citationStatements = sourceResource.listProperties(OwlUtil.propSourceHasCitation).toList();
255
        if(citationStatements.size()>1){
256
            logger.error("More than one citations found for source. Choosing one arbitrarily. - "+sourceResource.toString());
257
        }
258
        if(!citationStatements.isEmpty()){
259
            Statement citationStatement = citationStatements.iterator().next();
260
            Resource citationResource = model.createResource(citationStatement.getObject().toString());
261
            Reference reference = findReference(citationResource, repo);
262
            if(reference==null){
263
                reference = createReference(citationResource, model);
264
            }
265
            source.setCitation(reference);
266
        }
267
        return source;
268
    }
269

  
270
    static Reference createReference(Resource citationResource, Model model){
271
        String titleString = citationResource.getProperty(OwlUtil.propReferenceTitle).getString();
272
        Reference citation = ReferenceFactory.newGeneric();
273
        citation.setTitle(titleString);
274
        return citation;
275
    }
276

  
277
    static TermVocabulary createVocabulary(Resource vocabularyResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
278
        TermType termType = TermType.getByKey(vocabularyResource.getProperty(OwlUtil.propType).getString());
279
        // create new vocabulary
280
        TermVocabulary vocabulary = TermVocabulary.NewInstance(termType);
281
        vocabulary.setUuid(UUID.fromString(vocabularyResource.getProperty(OwlUtil.propUuid).getString()));
282

  
283
        // voc URI
284
        String vocUriString = vocabularyResource.hasProperty(OwlUtil.propUri)?vocabularyResource.getProperty(OwlUtil.propUri).getString():null;
285
        if(CdmUtils.isNotBlank(vocUriString)){
286
            vocabulary.setUri(URI.create(vocUriString));
287
        }
288

  
289
        // voc representations
290
        Set<Representation> vocRepresentations = new HashSet<>();
291
        vocabularyResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->vocRepresentations.add(OwlImportUtil.createRepresentation(repo, r, model)));
292
        if(vocRepresentations.isEmpty()){
293
            logger.error("No representations found for vocabulary: "+vocabularyResource.getProperty(OwlUtil.propUuid));
294
        }
295
        vocRepresentations.forEach(rep->vocabulary.addRepresentation(rep));
296

  
297
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(vocabularyResource.getURI());
298
        importSource.setCitation(state.getConfig().getSourceReference());
299
        vocabulary.addSource(importSource);
300

  
301

  
302
        return vocabulary;
303
    }
304

  
305
    static Media createMedia(Resource mediaResource, StructureTreeOwlImportState state){
306
        URI mediaUri = URI.create(mediaResource.getProperty(OwlUtil.propMediaUri).getString());
307
        // create new media
308
        Media media = Media.NewInstance(mediaUri, null, null, null);
309
        media.setUuid(UUID.fromString(mediaResource.getProperty(OwlUtil.propUuid).getString()));
310

  
311
        if(mediaResource.hasProperty(OwlUtil.propMediaTitle)){
312
            // TODO: support multiple language titles
313
            media.putTitle(Language.DEFAULT(), mediaResource.getProperty(OwlUtil.propMediaTitle).getString());
314
        }
315

  
316
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(mediaResource.getURI());
317
        importSource.setCitation(state.getConfig().getSourceReference());
318
        media.addSource(importSource);
319

  
320
        return media;
321
    }
322

  
323
    static Representation createRepresentation(ICdmRepository repo, Statement repr, Model model) {
324
        Resource repsentationResource = model.createResource(repr.getObject().toString());
325

  
326
        String languageLabel = repsentationResource.getProperty(OwlUtil.propLanguage).getString();
327
        UUID languageUuid = UUID.fromString(repsentationResource.getProperty(OwlUtil.propLanguageUuid).getString());
328
        Language language = Language.getLanguageFromUuid(languageUuid);
329
        if(language==null){
330
            language = repo.getTermService().getLanguageByLabel(languageLabel);
331
        }
332
        if(language==null){
333
            language = Language.getDefaultLanguage();
334
        }
335

  
336
        String abbreviatedLabel = repsentationResource.hasProperty(OwlUtil.propLabelAbbrev)?repsentationResource.getProperty(OwlUtil.propLabelAbbrev).getString():null;
337
        String plural = repsentationResource.hasProperty(OwlUtil.propLabelPlural)?repsentationResource.getProperty(OwlUtil.propLabelPlural).getString():null;
338
        String label = repsentationResource.getProperty(OwlUtil.propLabel).getString();
339
        String description = repsentationResource.hasProperty(OwlUtil.propDescription)?repsentationResource.getProperty(OwlUtil.propDescription).getString():null;
340
        Representation representation = Representation.NewInstance(description, label, abbreviatedLabel, language);
341
        representation.setPlural(plural);
342

  
343
        return representation;
344
    }
345

  
346
}
1
/**
2
* Copyright (C) 2019 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
package eu.etaxonomy.cdm.io.descriptive.owl.in;
10

  
11
import java.net.URI;
12
import java.util.Collections;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.UUID;
17

  
18
import com.hp.hpl.jena.rdf.model.Model;
19
import com.hp.hpl.jena.rdf.model.Resource;
20
import com.hp.hpl.jena.rdf.model.Statement;
21

  
22
import eu.etaxonomy.cdm.api.application.ICdmRepository;
23
import eu.etaxonomy.cdm.common.CdmUtils;
24
import eu.etaxonomy.cdm.io.descriptive.owl.OwlUtil;
25
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
26
import eu.etaxonomy.cdm.model.common.Language;
27
import eu.etaxonomy.cdm.model.description.Character;
28
import eu.etaxonomy.cdm.model.description.Feature;
29
import eu.etaxonomy.cdm.model.description.MeasurementUnit;
30
import eu.etaxonomy.cdm.model.description.State;
31
import eu.etaxonomy.cdm.model.description.StatisticalMeasure;
32
import eu.etaxonomy.cdm.model.media.Media;
33
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
34
import eu.etaxonomy.cdm.model.reference.Reference;
35
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
36
import eu.etaxonomy.cdm.model.term.DefinedTerm;
37
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
38
import eu.etaxonomy.cdm.model.term.Representation;
39
import eu.etaxonomy.cdm.model.term.TermTreeNode;
40
import eu.etaxonomy.cdm.model.term.TermType;
41
import eu.etaxonomy.cdm.model.term.TermVocabulary;
42

  
43
/**
44
 * @author pplitzner
45
 * @since May 26, 2019
46
 *
47
 */
48
public class OwlImportUtil {
49

  
50
    static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(OwlImportUtil.class);
51

  
52
    private static void addFeatureProperties(Feature feature, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
53
        if(termResource.hasProperty(OwlUtil.propFeatureIsCategorical)){
54
            feature.setSupportsCategoricalData(termResource.getProperty(OwlUtil.propFeatureIsCategorical).getBoolean());
55
        }
56
        if(termResource.hasProperty(OwlUtil.propFeatureIsQuantitative)){
57
            feature.setSupportsQuantitativeData(termResource.getProperty(OwlUtil.propFeatureIsQuantitative).getBoolean());
58
        }
59
        // import measurement units
60
        Set<MeasurementUnit> measurementUnits = new HashSet<>();
61
        List<Statement> measurementUnitStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedMeasurementUnit).toList();
62
        for (Statement statement : measurementUnitStatements) {
63
            Resource measurementUnitResource = model.createResource(statement.getObject().toString());
64
            MeasurementUnit measurementUnit = findTerm(MeasurementUnit.class, measurementUnitResource, repo, model, state);
65
            if(measurementUnit==null){
66
                measurementUnit = MeasurementUnit.NewInstance();
67
                addTermProperties(measurementUnit, measurementUnitResource, repo, model, state);
68
            }
69
            measurementUnits.add(measurementUnit);
70
        }
71
        measurementUnits.forEach(unit->feature.addRecommendedMeasurementUnit(unit));
72
        // import modifier TODO: create entire vocabulary if it cannot be found
73
        Set<TermVocabulary<DefinedTerm>> modifierVocs = new HashSet<>();
74
        List<Statement> modifierEnumStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedModifierEnumeration).toList();
75
        for (Statement statement : modifierEnumStatements) {
76
            Resource modifierEnumResource = model.createResource(statement.getObject().toString());
77
            TermVocabulary modifierVoc = findVocabulary(modifierEnumResource, repo, model, state);
78
            if(modifierVoc!=null){
79
                modifierVocs.add(modifierVoc);
80
            }
81
        }
82
        modifierVocs.forEach(modiferVoc->feature.addRecommendedModifierEnumeration(modiferVoc));
83
        // import statistical measures
84
        Set<StatisticalMeasure> statisticalMeasures = new HashSet<>();
85
        List<Statement> statisticalMeasureStatements = termResource.listProperties(OwlUtil.propFeatureHasRecommendedStatisticalMeasure).toList();
86
        for (Statement statement : statisticalMeasureStatements) {
87
            Resource statisticalMeasureResource = model.createResource(statement.getObject().toString());
88
            StatisticalMeasure statisticalMeasure = findTerm(StatisticalMeasure.class, statisticalMeasureResource, repo, model, state);
89
            if(statisticalMeasure==null){
90
                statisticalMeasure = StatisticalMeasure.NewInstance();
91
                addTermProperties(statisticalMeasure, statisticalMeasureResource, repo, model, state);
92
            }
93
            statisticalMeasures.add(statisticalMeasure);
94
        }
95
        statisticalMeasures.forEach(statisticalMeasure->feature.addRecommendedStatisticalMeasure(statisticalMeasure));
96
        // import categorical enums TODO: create entire vocabulary if it cannot be found
97
        Set<TermVocabulary<State>> stateVocs = new HashSet<>();
98
        List<Statement> stateVocStatements = termResource.listProperties(OwlUtil.propFeatureHasSupportedCategoricalEnumeration).toList();
99
        for (Statement statement : stateVocStatements) {
100
            Resource stateVocResource = model.createResource(statement.getObject().toString());
101
            TermVocabulary stateVoc = findVocabulary(stateVocResource, repo, model, state);
102
            if(stateVoc!=null){
103
                stateVocs.add(stateVoc);
104
            }
105
        }
106
        stateVocs.forEach(stateVoc->feature.addSupportedCategoricalEnumeration(stateVoc));
107
    }
108

  
109
    private static void addCharacterProperties(Character character, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
110
        addFeatureProperties(character, termResource, repo, model, state);
111
        // TODO import/export of complete term tree of structures and properties belonging to a character is necessary
112
        // import structure
113
        Statement structureStatement = termResource.getProperty(OwlUtil.propCharacterHasStructure);
114
        Resource structureResource = model.createResource(structureStatement.getObject().toString());
115
        TermTreeNode structureNode = findNode(structureResource, repo, model, state);
116
        if(structureNode!=null){
117
            character.setStructure(structureNode);
118
        }
119
        // import property
120
        Statement propertyStatement = termResource.getProperty(OwlUtil.propCharacterHasProperty);
121
        Resource propertyResource = model.createResource(propertyStatement.getObject().toString());
122
        TermTreeNode propertyNode = findNode(propertyResource, repo, model, state);
123
        if(propertyNode!=null){
124
            character.setProperty(propertyNode);
125
        }
126
        // import structure modifier
127
        if(termResource.hasProperty(OwlUtil.propCharacterHasStructureModfier)){
128
            Statement structureModifierStatement = termResource.getProperty(OwlUtil.propCharacterHasStructureModfier);
129
            Resource structureModifierResource = model.createResource(structureModifierStatement.getObject().toString());
130
            DefinedTerm structureModifier = findTerm(DefinedTerm.class, structureModifierResource, repo, model, state);
131
            character.setStructureModifier(structureModifier);
132
        }
133
    }
134

  
135
    private static void addTermProperties(DefinedTermBase term, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
136
        term.setUuid(UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString()));
137

  
138
        // term URI
139
        String uriString = termResource.hasProperty(OwlUtil.propUri)?termResource.getProperty(OwlUtil.propUri).getString():null;
140
        if(CdmUtils.isNotBlank(uriString)){
141
            term.setUri(URI.create(uriString));
142
        }
143
        // symbol
144
        String symbolString = termResource.hasProperty(OwlUtil.propTermSymbol)?termResource.getProperty(OwlUtil.propTermSymbol).getString():null;
145
        if(CdmUtils.isNotBlank(symbolString)){
146
            term.setSymbol(symbolString);
147
        }
148
        // symbol2
149
        String symbol2String = termResource.hasProperty(OwlUtil.propTermSymbol2)?termResource.getProperty(OwlUtil.propTermSymbol2).getString():null;
150
        if(CdmUtils.isNotBlank(symbol2String)){
151
            term.setSymbol2(symbol2String);
152
        }
153
        // idInVocabulary
154
        String idInVocabularyString = termResource.hasProperty(OwlUtil.propTermIdInVocabulary)?termResource.getProperty(OwlUtil.propTermIdInVocabulary).getString():null;
155
        if(CdmUtils.isNotBlank(idInVocabularyString)){
156
            term.setIdInVocabulary(idInVocabularyString);
157
        }
158

  
159
        // import representations
160
        Set<Representation> representations = new HashSet<>();
161
        termResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->representations.add(OwlImportUtil.createRepresentation(repo, r, model)));
162
        if(representations.isEmpty()){
163
            logger.error("No representations found for term: "+termResource.getProperty(OwlUtil.propUuid));
164
        }
165
        representations.forEach(rep->term.addRepresentation(rep));
166

  
167
        // import sources
168
        Set<IdentifiableSource> sources = new HashSet<>();
169
        termResource.listProperties(OwlUtil.propTermHasSource).forEachRemaining(sourceStatement->sources.add(OwlImportUtil.createSource(sourceStatement, repo, model)));
170
        sources.forEach(source->term.addSource(source));
171

  
172
        // add import source
173
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(termResource.getURI());
174
        importSource.setCitation(state.getConfig().getSourceReference());
175
        term.addSource(importSource);
176
    }
177

  
178
    private static <T extends DefinedTermBase> T findTerm(Class<T> clazz, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
179
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
180
        List<T> terms = repo.getTermService().find(clazz, Collections.singleton(termUuid));
181
        if(!terms.isEmpty()){
182
            return terms.iterator().next();
183
        }
184
        return null;
185
    }
186

  
187
    private static TermVocabulary findVocabulary(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
188
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
189
        return repo.getVocabularyService().find(termUuid);
190
    }
191

  
192
    private static TermTreeNode findNode(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
193
        UUID uuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
194
        return repo.getFeatureNodeService().find(uuid);
195
    }
196

  
197
    private static Reference findReference(Resource resource, ICdmRepository repo){
198
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
199
        return repo.getReferenceService().find(uuid);
200
    }
201

  
202
    static Media findMedia(Resource resource, ICdmRepository repo){
203
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
204
        return repo.getMediaService().find(uuid);
205
    }
206

  
207
    static Feature createFeature(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
208
        Feature feature = findTerm(Feature.class, termResource, repo, model, state);
209
        if(feature==null){
210
            feature = Feature.NewInstance();
211
            addFeatureProperties(feature, termResource, repo, model, state);
212
        }
213
        return feature;
214
    }
215

  
216
    private static Character createCharacter(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
217
        Character character = findTerm(Character.class, termResource, repo, model, state);
218
        if(character==null){
219
            character = Character.NewInstance();
220
            addCharacterProperties(character, termResource, repo, model, state);
221
        }
222
        return character;
223
    }
224

  
225
    static DefinedTermBase createTerm(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
226
        TermType termType = TermType.getByKey(termResource.getProperty(OwlUtil.propType).getString());
227
        DefinedTermBase term = null;
228
        // create new term
229
        if(termType.equals(TermType.Feature)){
230
            term = createFeature(termResource, repo, model, state);
231
        }
232
        else if(termType.equals(TermType.Character)){
233
            term = createCharacter(termResource, repo, model, state);
234
        }
235
        else{
236
            term = DefinedTerm.NewInstance(termType);
237
        }
238
        addTermProperties(term, termResource, repo, model, state);
239
        return term;
240
    }
241

  
242
    static IdentifiableSource createSource(Statement sourceStatement, ICdmRepository repo, Model model) {
243
        Resource sourceResource = model.createResource(sourceStatement.getObject().toString());
244

  
245
        String typeString = sourceResource.getProperty(OwlUtil.propSourceType).getString();
246
        IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.getByKey(typeString));
247

  
248
        if(sourceResource.hasProperty(OwlUtil.propSourceIdInSource)){
249
            String idInSource = sourceResource.getProperty(OwlUtil.propSourceIdInSource).getString();
250
            source.setIdInSource(idInSource);
251
        }
252

  
253
        // import citation
254
        List<Statement> citationStatements = sourceResource.listProperties(OwlUtil.propSourceHasCitation).toList();
255
        if(citationStatements.size()>1){
256
            logger.error("More than one citations found for source. Choosing one arbitrarily. - "+sourceResource.toString());
257
        }
258
        if(!citationStatements.isEmpty()){
259
            Statement citationStatement = citationStatements.iterator().next();
260
            Resource citationResource = model.createResource(citationStatement.getObject().toString());
261
            Reference reference = findReference(citationResource, repo);
262
            if(reference==null){
263
                reference = createReference(citationResource, model);
264
            }
265
            source.setCitation(reference);
266
        }
267
        return source;
268
    }
269

  
270
    static Reference createReference(Resource citationResource, Model model){
271
        String titleString = citationResource.getProperty(OwlUtil.propReferenceTitle).getString();
272
        Reference citation = ReferenceFactory.newGeneric();
273
        citation.setTitle(titleString);
274
        return citation;
275
    }
276

  
277
    static TermVocabulary createVocabulary(Resource vocabularyResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
278
        TermType termType = TermType.getByKey(vocabularyResource.getProperty(OwlUtil.propType).getString());
279
        // create new vocabulary
280
        TermVocabulary vocabulary = TermVocabulary.NewInstance(termType);
281
        vocabulary.setUuid(UUID.fromString(vocabularyResource.getProperty(OwlUtil.propUuid).getString()));
282

  
283
        // voc URI
284
        String vocUriString = vocabularyResource.hasProperty(OwlUtil.propUri)?vocabularyResource.getProperty(OwlUtil.propUri).getString():null;
285
        if(CdmUtils.isNotBlank(vocUriString)){
286
            vocabulary.setUri(URI.create(vocUriString));
287
        }
288

  
289
        // voc representations
290
        Set<Representation> vocRepresentations = new HashSet<>();
291
        vocabularyResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->vocRepresentations.add(OwlImportUtil.createRepresentation(repo, r, model)));
292
        if(vocRepresentations.isEmpty()){
293
            logger.error("No representations found for vocabulary: "+vocabularyResource.getProperty(OwlUtil.propUuid));
294
        }
295
        vocRepresentations.forEach(rep->vocabulary.addRepresentation(rep));
296

  
297
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(vocabularyResource.getURI());
298
        importSource.setCitation(state.getConfig().getSourceReference());
299
        vocabulary.addSource(importSource);
300

  
301

  
302
        return vocabulary;
303
    }
304

  
305
    static Media createMedia(Resource mediaResource, StructureTreeOwlImportState state){
306
        URI mediaUri = URI.create(mediaResource.getProperty(OwlUtil.propMediaUri).getString());
307
        // create new media
308
        Media media = Media.NewInstance(mediaUri, null, null, null);
309
        media.setUuid(UUID.fromString(mediaResource.getProperty(OwlUtil.propUuid).getString()));
310

  
311
        if(mediaResource.hasProperty(OwlUtil.propMediaTitle)){
312
            // TODO: support multiple language titles
313
            media.putTitle(Language.DEFAULT(), mediaResource.getProperty(OwlUtil.propMediaTitle).getString());
314
        }
315

  
316
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(mediaResource.getURI());
317
        importSource.setCitation(state.getConfig().getSourceReference());
318
        media.addSource(importSource);
319

  
320
        return media;
321
    }
322

  
323
    static Representation createRepresentation(ICdmRepository repo, Statement repr, Model model) {
324
        Resource repsentationResource = model.createResource(repr.getObject().toString());
325

  
326
        String languageLabel = repsentationResource.getProperty(OwlUtil.propLanguage).getString();
327
        UUID languageUuid = UUID.fromString(repsentationResource.getProperty(OwlUtil.propLanguageUuid).getString());
328
        Language language = Language.getLanguageFromUuid(languageUuid);
329
        if(language==null){
330
            language = repo.getTermService().getLanguageByLabel(languageLabel);
331
        }
332
        if(language==null){
333
            language = Language.getDefaultLanguage();
334
        }
335

  
336
        String abbreviatedLabel = repsentationResource.hasProperty(OwlUtil.propLabelAbbrev)?repsentationResource.getProperty(OwlUtil.propLabelAbbrev).getString():null;
337
        String plural = repsentationResource.hasProperty(OwlUtil.propLabelPlural)?repsentationResource.getProperty(OwlUtil.propLabelPlural).getString():null;
338
        String label = repsentationResource.getProperty(OwlUtil.propLabel).getString();
339
        String description = repsentationResource.hasProperty(OwlUtil.propDescription)?repsentationResource.getProperty(OwlUtil.propDescription).getString():null;
340
        Representation representation = Representation.NewInstance(description, label, abbreviatedLabel, language);
341
        representation.setPlural(plural);
342

  
343
        return representation;
344
    }
345

  
346
}
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/descriptive/word/out/WordExport.java
20 20
import eu.etaxonomy.cdm.io.common.CdmExportBase;
21 21
import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
22 22
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
23
import eu.etaxonomy.cdm.model.term.FeatureNode;
23
import eu.etaxonomy.cdm.model.term.TermTreeNode;
24 24
import eu.etaxonomy.cdm.model.term.FeatureTree;
25 25

  
26 26
/**
......
46 46

  
47 47
        FeatureTree featureTree = state.getConfig().getFeatureTree();
48 48
        featureTree = getFeatureTreeService().load(featureTree.getUuid());
49
        FeatureNode rootNode = featureTree.getRoot();
49
        TermTreeNode rootNode = featureTree.getRoot();
50 50

  
51 51
        try {
52 52
            exportStream = generateDocx4JDocument(rootNode);
......
60 60
        return;
61 61
    }
62 62

  
63
    private ByteArrayOutputStream generateDocx4JDocument(FeatureNode rootNode) throws Exception {
63
    private ByteArrayOutputStream generateDocx4JDocument(TermTreeNode rootNode) throws Exception {
64 64
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("eu/etaxonomy/cdm/io/word/out/template.docx");
65 65
        WordprocessingMLPackage wordPackage = WordprocessingMLPackage.load(resourceAsStream);
66 66
        MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
......
110 110
//        return new JAXBElement( new QName(Namespaces.NS_WORD12, "fldChar"), org.docx4j.wml.FldChar.class, fldchar);
111 111
//    }
112 112

  
113
    private void addChildNode(FeatureNode<?> node, MainDocumentPart mainDocumentPart, int indent) throws Exception{
113
    private void addChildNode(TermTreeNode<?> node, MainDocumentPart mainDocumentPart, int indent) throws Exception{
114 114
        String styleId = "Heading"+indent;
115 115

  
116
        for (FeatureNode childNode : node.getChildNodes()) {
116
        for (TermTreeNode childNode : node.getChildNodes()) {
117 117
            DefinedTermBase term = childNode.getTerm();
118 118
            mainDocumentPart.addStyledParagraphOfText(styleId, term.getLabel());
119 119
            if(term.getDescription()!=null){
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/jaxb/JaxbImport.java
37 37
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
38 38
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
39 39
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
40
import eu.etaxonomy.cdm.model.term.FeatureNode;
40
import eu.etaxonomy.cdm.model.term.TermTreeNode;
41 41
import eu.etaxonomy.cdm.model.term.FeatureTree;
42 42
import eu.etaxonomy.cdm.model.term.TermVocabulary;
43 43

  
......
118 118
		List<TypeDesignationBase<?>> typeDesignations;
119 119
		List<SpecimenOrObservationBase> occurrences;
120 120
		List<FeatureTree> featureTrees;
121
		List<FeatureNode> featureNodes;
121
		List<TermTreeNode> featureNodes;
122 122
		List<Media> media;
123 123
		List<LanguageStringBase> languageData;
124 124
		List<TermVocabulary<DefinedTermBase>> termVocabularies;
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/markup/MarkupImportState.java
35 35
import eu.etaxonomy.cdm.model.occurrence.Collection;
36 36
import eu.etaxonomy.cdm.model.reference.Reference;
37 37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.term.FeatureNode;
38
import eu.etaxonomy.cdm.model.term.TermTreeNode;
39 39

  
40 40
/**
41 41
 * @author a.mueller
......
51 51
	private UnmatchedLeads unmatchedLeads;
52 52
	private boolean onlyNumberedTaxaExist; //attribute in <key>
53 53

  
54
	private Set<FeatureNode> featureNodesToSave = new HashSet<FeatureNode>();
54
	private Set<TermTreeNode> featureNodesToSave = new HashSet<TermTreeNode>();
55 55

  
56 56
	private Set<PolytomousKeyNode> polytomousKeyNodesToSave = new HashSet<>();
57 57

  
......
115 115
	 * @see MarkupImportConfigurator#getNewState()
116 116
	 */
117 117
	protected void reset(){
118
		featureNodesToSave = new HashSet<FeatureNode>();
118
		featureNodesToSave = new HashSet<TermTreeNode>();
119 119
		polytomousKeyNodesToSave = new HashSet<PolytomousKeyNode>();
120 120
		currentKey = null;
121 121
		defaultLanguage = null;
......
154 154
		this.unmatchedLeads = unmatchedKeys;
155 155
	}
156 156

  
157
	public void setFeatureNodesToSave(Set<FeatureNode> featureNodesToSave) {
157
	public void setFeatureNodesToSave(Set<TermTreeNode> featureNodesToSave) {
158 158
		this.featureNodesToSave = featureNodesToSave;
159 159
	}
160 160

  
161
	public Set<FeatureNode> getFeatureNodesToSave() {
161
	public Set<TermTreeNode> getFeatureNodesToSave() {
162 162
		return featureNodesToSave;
163 163
	}
164 164

  
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/sdd/in/SDDImport.java
83 83
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
84 84
import eu.etaxonomy.cdm.model.term.DefinedTerm;
85 85
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
86
import eu.etaxonomy.cdm.model.term.FeatureNode;
87 86
import eu.etaxonomy.cdm.model.term.FeatureTree;
88 87
import eu.etaxonomy.cdm.model.term.Representation;
89 88
import eu.etaxonomy.cdm.model.term.TermBase;
89
import eu.etaxonomy.cdm.model.term.TermTreeNode;
90 90
import eu.etaxonomy.cdm.model.term.TermType;
91 91
import eu.etaxonomy.cdm.model.term.TermVocabulary;
92 92

  
......
106 106
    private Map<String,String> citations = new HashMap<>();
107 107
    private Map<String,String> defaultUnitPrefixes = new HashMap<>();
108 108
    private Map<String,Person> editors = new HashMap<>();
109
    private Map<String,FeatureNode<Feature>> featureNodes = new HashMap<>();
109
    private Map<String,TermTreeNode<Feature>> featureNodes = new HashMap<>();
110 110
    private Map<String,Feature> features = new HashMap<>();
111 111
    private Map<String,String> locations = new HashMap<>();
112 112
    private Map<String,List<CdmBase>> mediaObject_ListCdmBase = new HashMap<>();
......
1753 1753

  
1754 1754
					FeatureTree featureTree =  FeatureTree.NewInstance();
1755 1755
					importRepresentation(elCharacterTree, sddNamespace, featureTree, "", cdmState);
1756
					FeatureNode<Feature> root = featureTree.getRoot();
1756
					TermTreeNode<Feature> root = featureTree.getRoot();
1757 1757
					List<Element> listeOfNodes = elCharacterTree.getChildren("Nodes", sddNamespace);
1758 1758

  
1759 1759
					//Nodes of CharacterTrees in SDD always refer to DescriptiveConcepts
......
1785 1785
	 * @param root
1786 1786
	 * @param elNodes
1787 1787
	 */
1788
	private void handleCharacterNodes(Namespace sddNamespace, FeatureNode<Feature> root, Element elNodes) {
1788
	private void handleCharacterNodes(Namespace sddNamespace, TermTreeNode<Feature> root, Element elNodes) {
1789 1789
		List<Element> listNodes = elNodes.getChildren("Node", sddNamespace);
1790 1790
		if (listNodes != null) {
1791 1791
			for (Element elNode : listNodes){
1792 1792
				String idN = elNode.getAttributeValue("id");
1793
				FeatureNode<Feature> fn = null;
1793
				TermTreeNode<Feature> fn = null;
1794 1794
				Feature dc = null;
1795 1795
				if (idN!=null) {
1796 1796
					// DescriptiveConcepts are used as nodes in CharacterTrees
......
1804 1804
					if (elParent!=null){
1805 1805
						String refP = elParent.getAttributeValue("ref");
1806 1806
						if (refP!=null) {
1807
							FeatureNode<Feature> parent = featureNodes.get(refP);
1807
							TermTreeNode<Feature> parent = featureNodes.get(refP);
1808 1808
							if (parent==null){
1809 1809
							    // if no parent found or the reference is broken, add the node to the root of the tree
1810 1810
							    fn = (dc==null)?root.addChild():root.addChild(dc);
......
1831 1831
				Element elParent = elCharNode.getChild("Parent", sddNamespace);
1832 1832
				Element elCharacter = elCharNode.getChild("Character", sddNamespace);
1833 1833
				Element elDependencyRules = elCharNode.getChild("DependencyRules", sddNamespace);
1834
				FeatureNode<Feature> fn = null;
1834
				TermTreeNode<Feature> fn = null;
1835 1835

  
1836 1836
                if (elParent!=null){
1837 1837
                    String refP = elParent.getAttributeValue("ref");
1838 1838
                    if ((refP!=null)&&(!refP.equals(""))) {
1839
                        FeatureNode<Feature> parent = featureNodes.get(refP);
1839
                        TermTreeNode<Feature> parent = featureNodes.get(refP);
1840 1840
                        if (parent==null){
1841 1841
                            parent = root; // if no parent found or the reference is broken, add the node to the root of the tree
1842 1842
                        }
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/sdd/out/SDDDataSet.java
79 79
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
80 80
import eu.etaxonomy.cdm.model.term.DefinedTerm;
81 81
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
82
import eu.etaxonomy.cdm.model.term.FeatureNode;
82
import eu.etaxonomy.cdm.model.term.TermTreeNode;
83 83
import eu.etaxonomy.cdm.model.term.FeatureTree;
84 84
import eu.etaxonomy.cdm.model.term.Representation;
85 85
import eu.etaxonomy.cdm.model.term.TermVocabulary;
......
133 133

  
134 134
    @XmlElementWrapper(name = "FeatureData")
135 135
        @XmlElements({
136
        @XmlElement(name = "FeatureNode", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = FeatureNode.class),
136
        @XmlElement(name = "FeatureNode", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = TermTreeNode.class),
137 137
        @XmlElement(name = "FeatureTree", namespace = "http://etaxonomy.eu/cdm/model/description/1.0", type = FeatureTree.class)
138 138
    })
139 139
//    protected List<VersionableEntity> featureData;
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/sdd/out/SDDDocumentBuilder.java
78 78
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
79 79
import eu.etaxonomy.cdm.model.term.DefinedTerm;
80 80
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
81
import eu.etaxonomy.cdm.model.term.FeatureNode;
81
import eu.etaxonomy.cdm.model.term.TermTreeNode;
82 82
import eu.etaxonomy.cdm.model.term.FeatureTree;
83 83
import eu.etaxonomy.cdm.model.term.Representation;
84 84
import eu.etaxonomy.cdm.model.term.TermBase;
......
103 103
	private final Map<Person, String> agents = new HashMap<>();
104 104
	private final Map<TaxonName, String> taxonNames = new HashMap<>();
105 105
	private final Map<Feature, String> characters = new HashMap<>();
106
	private final Map<FeatureNode, String> featureNodes = new HashMap<>();
106
	private final Map<TermTreeNode, String> featureNodes = new HashMap<>();
107 107
	private final Map<Feature, String> descriptiveConcepts = new HashMap<>();
108 108
	private final Map<TaxonDescription, String> codedDescriptions = new HashMap<>();
109 109
	private final Map<Media, String> medias = new HashMap<>();
......
1199 1199
					elChartrees.appendChild(elChartree);
1200 1200
					ElementImpl elNodes = new ElementImpl(document, NODES);
1201 1201
					elChartree.appendChild(elNodes);
1202
					List<FeatureNode> roots = ft.getRootChildren();
1203
					for (Iterator<FeatureNode> fn = roots.iterator(); fn
1202
					List<TermTreeNode> roots = ft.getRootChildren();
1203
					for (Iterator<TermTreeNode> fn = roots.iterator(); fn
1204 1204
							.hasNext();) {
1205
						FeatureNode featureNode = fn.next();
1205
						TermTreeNode featureNode = fn.next();
1206 1206
						buildBranches(featureNode, elNodes, true);
1207 1207
					}
1208 1208
				}
......
1272 1272
		}
1273 1273
	}
1274 1274

  
1275
	public void buildBranches(FeatureNode<Feature> parent, ElementImpl element,
1275
	public void buildBranches(TermTreeNode<Feature> parent, ElementImpl element,
1276 1276
			boolean isRoot) {
1277
		List<FeatureNode<Feature>> children = parent.getChildNodes();
1277
		List<TermTreeNode<Feature>> children = parent.getChildNodes();
1278 1278
		if (!parent.isLeaf()) {
1279 1279
			ElementImpl elCharNode = new ElementImpl(document, NODE);
1280 1280
			charnodeCount = buildReference(parent, featuretrees, ID,
1281 1281
					elCharNode, "cn", charnodeCount);
1282
			FeatureNode grandparent = parent.getParent();
1282
			TermTreeNode grandparent = parent.getParent();
1283 1283
			if ((grandparent != null) && (!isRoot)) {
1284 1284
				ElementImpl elParent = new ElementImpl(document, PARENT);
1285 1285
				charnodeCount = buildReference(grandparent, featuretrees, REF,
......
1293 1293
					REF, elDescriptiveConcept, "dc", descriptiveConceptCount);
1294 1294
			elCharNode.appendChild(elDescriptiveConcept);
1295 1295
			element.appendChild(elCharNode);
1296
			for (Iterator<FeatureNode<Feature>> ifn = children.iterator(); ifn.hasNext();) {
1297
				FeatureNode fn = ifn.next();
1296
			for (Iterator<TermTreeNode<Feature>> ifn = children.iterator(); ifn.hasNext();) {
1297
				TermTreeNode fn = ifn.next();
1298 1298
				buildBranches(fn, element, false);
1299 1299
			}
1300 1300
		} else {
1301 1301
			ElementImpl elCharNode = new ElementImpl(document, CHAR_NODE);
1302 1302
			ElementImpl elParent = new ElementImpl(document, PARENT);
1303
			FeatureNode grandparent = parent.getParent();
1303
			TermTreeNode grandparent = parent.getParent();
1304 1304
			charnodeCount = buildReference(grandparent, featuretrees, REF,
1305 1305
					elParent, "cn", charnodeCount);
1306 1306
			charnodeCount = buildReference(parent, featuretrees, ID,
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/taxonx2013/TaxonXTreatmentExtractor.java
63 63
import eu.etaxonomy.cdm.model.taxon.Taxon;
64 64
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
65 65
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
66
import eu.etaxonomy.cdm.model.term.FeatureNode;
67 66
import eu.etaxonomy.cdm.model.term.FeatureTree;
67
import eu.etaxonomy.cdm.model.term.TermTreeNode;
68 68
import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
69 69
import eu.etaxonomy.cdm.persistence.query.MatchMode;
70 70
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
......
321 321
            proibiospheretree = FeatureTree.NewInstance();
322 322
            proibiospheretree.setUuid(proIbioTreeUUID);
323 323
        }
324
        //        FeatureNode root = proibiospheretree.getRoot();
325
        FeatureNode root2 = proibiospheretree.getRoot();
324

  
325
        TermTreeNode root2 = proibiospheretree.getRoot();
326 326
        if (root2 != null){
327 327
            int nbChildren = root2.getChildCount()-1;
328 328
            while (nbChildren>-1){
cdmlib-io/src/test/java/eu/etaxonomy/cdm/io/jaxb/FeatureTest.java
15 15
import java.io.InputStreamReader;
16 16
import java.net.URI;
17 17

  
18
import org.junit.Ignore;
19 18
import org.junit.Test;
20 19

  
21 20
import eu.etaxonomy.cdm.model.description.Feature;
22
import eu.etaxonomy.cdm.model.term.FeatureNode;
21
import eu.etaxonomy.cdm.model.term.TermTreeNode;
23 22
import eu.etaxonomy.cdm.model.term.FeatureTree;
24 23

  
25
@Ignore  //does not work anymore since FeatureNode + Tree was moved to term package
24
//@Ignore  //does not work anymore since FeatureNode + Tree was moved to term package
26 25
public class FeatureTest {
27 26

  
28 27
	    private String resource = "/eu/etaxonomy/cdm/io/jaxb/FeatureTest.xml";
......
40 39
			assertNotNull("Feature must not be null", feature);
41 40

  
42 41
			assertNotNull("FeatureTree.root must not be null", featureTree.getRoot());
43
			FeatureNode<Feature> root = featureTree.getRoot();
42
			TermTreeNode<Feature> root = featureTree.getRoot();
44 43
			assertNotNull("FeatureNode.feature must not be null", root.getTerm());
45 44
			assertEquals("FeatureNode.feature must equal Feature", feature, root.getTerm());
46 45

  
cdmlib-io/src/test/java/eu/etaxonomy/cdm/io/owl/out/OwlExportTest.java
31 31
import eu.etaxonomy.cdm.io.descriptive.owl.out.StructureTreeOwlExportConfigurator;
32 32
import eu.etaxonomy.cdm.model.common.CdmBase;
33 33
import eu.etaxonomy.cdm.model.description.Feature;
34
import eu.etaxonomy.cdm.model.term.FeatureNode;
35 34
import eu.etaxonomy.cdm.model.term.FeatureTree;
35
import eu.etaxonomy.cdm.model.term.TermTreeNode;
36 36
import eu.etaxonomy.cdm.model.term.TermType;
37 37
import eu.etaxonomy.cdm.model.term.TermVocabulary;
38 38
import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;
......
81 81

  
82 82
        Feature featureA = Feature.NewInstance("A", "A", "A");
83 83
        voc.addTerm(featureA);
84
        FeatureNode nodeA = tree.getRoot().addChild(featureA);
84
        TermTreeNode<Feature> nodeA = tree.getRoot().addChild(featureA);
85 85

  
86 86
        Feature featureA1 = Feature.NewInstance("A1", "A1", "A1");
87 87
        voc.addTerm(featureA1);
88
        FeatureNode nodeA1 = nodeA.addChild(featureA1);
88
        TermTreeNode<Feature> nodeA1 = nodeA.addChild(featureA1);
89 89

  
90 90
        Feature featureA2 = Feature.NewInstance("A2", "A2", "A2");
91 91
        voc.addTerm(featureA2);
92
        FeatureNode nodeA2 = nodeA.addChild(featureA2);
92
        TermTreeNode<Feature> nodeA2 = nodeA.addChild(featureA2);
93 93

  
94 94
        Feature featureB = Feature.NewInstance("B", "B", "B");
95 95
        voc.addTerm(featureB);
96
        FeatureNode nodeB = tree.getRoot().addChild(featureB);
96
        TermTreeNode<Feature> nodeB = tree.getRoot().addChild(featureB);
97 97

  
98 98
        Feature featureB1 = Feature.NewInstance("B", "B1", "B1");
99 99
        voc.addTerm(featureB1);
100
        FeatureNode nodeB1 = nodeB.addChild(featureB1);
100
        TermTreeNode<Feature> nodeB1 = nodeB.addChild(featureB1);
101 101

  
102 102
        Feature featureC = Feature.NewInstance("C", "C", "C");
103 103
        voc.addTerm(featureC);
104
        FeatureNode nodeC = tree.getRoot().addChild(featureC);
104
        TermTreeNode<Feature> nodeC = tree.getRoot().addChild(featureC);
105 105

  
106 106
        featureTreeService.save(tree);
107 107
        return Collections.singletonList(tree.getUuid());
cdmlib-io/src/test/java/eu/etaxonomy/cdm/test/integration/TestCdmDbComparator.java
110 110
//			"DeterminationEvent_Annotation",
111 111
//			"DeterminationEvent_Marker",
112 112
//			"Extension",
113
			"FeatureNode",
113
			"TernRelation",
114 114
			"FeatureTree",
115 115
//			"FeatureTree_Representation",
116 116
//			"GatheringEvent",
cdmlib-io/src/test/resources/eu/etaxonomy/cdm/database/ClearDBDataSet.xml
170 170
  <ENTITYCONSTRAINTVIOLATION/>
171 171
  <EXTENSION/>
172 172
  <EXTENSION_AUD/>
173
  <FEATURENODE/>
174
  <FEATURENODE_AUD/>
175
  <FEATURENODE_DEFINEDTERMBASE_INAPPLICABLEIF/>
176
  <FEATURENODE_DEFINEDTERMBASE_INAPPLICABLEIF_AUD/>
177
  <FEATURENODE_DEFINEDTERMBASE_ONLYAPPLICABLE/>
178
  <FEATURENODE_DEFINEDTERMBASE_ONLYAPPLICABLE_AUD/>
179 173
  <FEATURETREE/>
180 174
  <FEATURETREE_ANNOTATION/>
181 175
  <FEATURETREE_ANNOTATION_AUD/>
......
337 331
  <REFERENCE_ORIGINALSOURCEBASE_AUD/>
338 332
  <REFERENCE_RIGHTSINFO/>
339 333
  <REFERENCE_RIGHTSINFO_AUD/>
334
  <REGISTRATION/>
340 335
  <REPRESENTATION_ANNOTATION/>
341 336
  <REPRESENTATION_ANNOTATION_AUD/>
342 337
  <REPRESENTATION_MARKER/>
......
431 426
  <TAXONRELATIONSHIP_AUD/>
432 427
  <TAXONRELATIONSHIP_MARKER/>
433 428
  <TAXONRELATIONSHIP_MARKER_AUD/>
429
  <TERMRELATION/>
430
  <TERMRELATION_AUD/>
431
  <TERMTREENODE_DEFINEDTERMBASE_INAPPLICABLEIF/>
432
  <TERMTREENODE_DEFINEDTERMBASE_INAPPLICABLEIF_AUD/>
433
  <TERMTREENODE_DEFINEDTERMBASE_ONLYAPPLICABLE/>
434
  <TERMTREENODE_DEFINEDTERMBASE_ONLYAPPLICABLE_AUD/>
434 435
  <TERMVOCABULARY_ANNOTATION/>
435 436
  <TERMVOCABULARY_ANNOTATION_AUD/>
436 437
  <TERMVOCABULARY_CREDIT/>
cdmlib-io/src/test/resources/eu/etaxonomy/cdm/database/ClearDB_with_Terms_DataSet.xml
1 1
<?xml version='1.0' encoding='UTF-8'?>
2
<dataset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../service/dataset.xsd">
2
<dataset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema/dataset.xsd">
3 3
<ADDRESS />
4 4
<ADDRESS_AUD />
5 5
<AGENTBASE />
......
56 56
<CLASSIFICATION_ORIGINALSOURCEBASE_AUD />
57 57
<CLASSIFICATION_RIGHTSINFO />
58 58
<CLASSIFICATION_RIGHTSINFO_AUD />
59
<!--<CLASSIFICATION_TAXONNODE />
60
  <CLASSIFICATION_TAXONNODE_AUD />-->
61 59
<COLLECTION />
62 60
<COLLECTION_ANNOTATION />
63 61
<COLLECTION_ANNOTATION_AUD />
......
177 175
<DETERMINATIONEVENT_REFERENCE_AUD />
178 176
<EXTENSION />
179 177
<EXTENSION_AUD />
180
<FEATURENODE />
181
<FEATURENODE_AUD />
182
<FEATURENODE_DEFINEDTERMBASE_INAPPLICABLEIF />
183
<FEATURENODE_DEFINEDTERMBASE_INAPPLICABLEIF_AUD />
184
<FEATURENODE_DEFINEDTERMBASE_ONLYAPPLICABLE />
185
<FEATURENODE_DEFINEDTERMBASE_ONLYAPPLICABLE_AUD />
186 178
<FEATURETREE />
187 179
<FEATURETREE_ANNOTATION />
188 180
<FEATURETREE_ANNOTATION_AUD />
......
441 433
<TAXONRELATIONSHIP_AUD/>
442 434
<TAXONRELATIONSHIP_MARKER/>
443 435
<TAXONRELATIONSHIP_MARKER_AUD/>
436
<TERMRELATION/>
437
<TERMRELATION_AUD/>
438
<TERMTREENODE_DEFINEDTERMBASE_INAPPLICABLEIF/>
439
<TERMTREENODE_DEFINEDTERMBASE_INAPPLICABLEIF_AUD/>
440
<TERMTREENODE_DEFINEDTERMBASE_ONLYAPPLICABLE/>
441
<TERMTREENODE_DEFINEDTERMBASE_ONLYAPPLICABLE_AUD/>
444 442
<TERMVOCABULARY />
445 443
<TERMVOCABULARY_AUD />
446 444
<TERMVOCABULARY_REPRESENTATION />
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/common/TreeIndex.java
17 17
import java.util.regex.Pattern;
18 18

  
19 19
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
20
import eu.etaxonomy.cdm.model.term.FeatureNode;
20
import eu.etaxonomy.cdm.model.term.TermTreeNode;
21 21

  
22 22
/**
23
 * A class to handle tree indexes as used in {@link TaxonNode}, {@link FeatureNode}
23
 * A class to handle tree indexes as used in {@link TaxonNode}, {@link TermTreeNode}
24 24
 * etc.<BR>
25 25
 * Might be come a hibernate user type in future.
26 26
 *
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/description/Character.java
25 25

  
26 26
import eu.etaxonomy.cdm.model.common.Language;
27 27
import eu.etaxonomy.cdm.model.term.DefinedTerm;
28
import eu.etaxonomy.cdm.model.term.FeatureNode;
28
import eu.etaxonomy.cdm.model.term.TermTreeNode;
29 29
import eu.etaxonomy.cdm.model.term.TermType;
30 30

  
31 31
/**
......
59 59
    @ManyToOne(fetch = FetchType.LAZY)
60 60
    @IndexedEmbedded
61 61
//    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
62
    private FeatureNode structure;
62
    private TermTreeNode structure;
63 63

  
64 64
    //#8120
65 65
    @XmlElement(name = "StructureModifier")
......
75 75
    @ManyToOne(fetch = FetchType.LAZY)
76 76
    @IndexedEmbedded
77 77
//    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
78
    private FeatureNode property;
78
    private TermTreeNode property;
79 79

  
80 80
    //#8120
81 81
    /**
......
107 107
     * @param property The property feature node for this character
108 108
     * @see #Feature()
109 109
     */
110
    public static Character NewInstance(FeatureNode structure, FeatureNode property){
110
    public static Character NewInstance(TermTreeNode structure, TermTreeNode property){
111 111
        return new Character(structure, property, null, null, null);
112 112
    }
113 113

  
......
130 130
     *            to be created
131 131
     * @see #Feature()
132 132
     */
133
    public static Character NewInstance(FeatureNode structure, FeatureNode property, String term, String label, String labelAbbrev){
133
    public static Character NewInstance(TermTreeNode structure, TermTreeNode property, String term, String label, String labelAbbrev){
134 134
        return new Character(structure, property, term, label, labelAbbrev);
135 135
    }
136 136

  
......
161 161
     *            to be created
162 162
     * @see #Feature()
163 163
     */
164
    protected Character(FeatureNode structure, FeatureNode property, String term, String label, String labelAbbrev) {
164
    protected Character(TermTreeNode structure, TermTreeNode property, String term, String label, String labelAbbrev) {
165 165
        super(term, label, labelAbbrev);
166 166
        this.setTermType(TermType.Character);
167 167
        this.structure = structure;
......
170 170

  
171 171
 // ****************** GETTER / SETTER *********************************************/
172 172

  
173
    public FeatureNode getStructure() {
173
    public TermTreeNode getStructure() {
174 174
        return structure;
175 175
    }
176
    public void setStructure(FeatureNode structure) {
176
    public void setStructure(TermTreeNode structure) {
177 177
        this.structure = structure;
178 178
    }
179 179

  
180
    public FeatureNode getProperty() {
180
    public TermTreeNode getProperty() {
181 181
        return property;
182 182
    }
183
    public void setProperty(FeatureNode property) {
183
    public void setProperty(TermTreeNode property) {
184 184
        this.property = property;
185 185
    }
186 186

  
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/description/PolytomousKeyNode.java
139 139
 */
140 140
@SuppressWarnings("serial")
141 141
@XmlAccessorType(XmlAccessType.FIELD)
142
@XmlType(name = "PolytomousKeyNode", propOrder = { "key", "parent", "children",
143
		"sortIndex", "nodeNumber", "statement", "question", "feature", "taxon",
144
		"subkey", "otherNode", "modifyingText" })
145
@XmlRootElement(name = "FeatureNode")
142
@XmlType(name = "PolytomousKeyNode", propOrder = {
143
        "key",
144
        "parent",
145
        "children",
146
		"sortIndex",
147
		"nodeNumber",
148
		"statement",
149
		"question",
150
		"feature",
151
		"taxon",
152
		"subkey",
153
		"otherNode",
154
		"modifyingText" })
155
@XmlRootElement(name = "FeaPolytomousKeyNodetureNode")
146 156
@Entity
147 157
@Audited
148 158
public class PolytomousKeyNode extends VersionableEntity implements IMultiLanguageTextHolder {
......
161 171
	@XmlElementWrapper(name = "Children")
162 172
	@XmlElement(name = "Child")
163 173
	// @OrderColumn("sortIndex") //JPA 2.0 same as @IndexColumn
164
	// @IndexColumn does not work because not every FeatureNode has a parent.
174
	// @IndexColumn does not work because not every PolytomousKeyNode has a parent.
165 175
	// But only NotNull will solve the problem (otherwise
166 176
	// we will need a join table
167 177
	// http://stackoverflow.com/questions/2956171/jpa-2-0-ordercolumn-annotation-in-hibernate-3-5
......
174 184
	@OrderBy("sortIndex")
175 185
	@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
176 186
	@Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE })
177
	private List<PolytomousKeyNode> children = new ArrayList<PolytomousKeyNode>();
187
	private List<PolytomousKeyNode> children = new ArrayList<>();
178 188

  
179 189

  
180 190

  
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/term/FeatureNode.java
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.term;
11

  
12
import java.util.ArrayList;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16

  
17
import javax.persistence.Column;
18
import javax.persistence.Entity;
19
import javax.persistence.FetchType;
20
import javax.persistence.Index;
21
import javax.persistence.JoinColumn;
22
import javax.persistence.JoinTable;
23
import javax.persistence.ManyToMany;
24
import javax.persistence.ManyToOne;
25
import javax.persistence.OneToMany;
26
import javax.persistence.OrderBy;
27
import javax.persistence.OrderColumn;
28
import javax.persistence.Table;
29
import javax.persistence.Transient;
30
import javax.validation.constraints.NotNull;
31
import javax.xml.bind.annotation.XmlAccessType;
32
import javax.xml.bind.annotation.XmlAccessorType;
33
import javax.xml.bind.annotation.XmlAttribute;
34
import javax.xml.bind.annotation.XmlElement;
35
import javax.xml.bind.annotation.XmlElementWrapper;
36
import javax.xml.bind.annotation.XmlIDREF;
37
import javax.xml.bind.annotation.XmlRootElement;
38
import javax.xml.bind.annotation.XmlSchemaType;
39
import javax.xml.bind.annotation.XmlType;
40

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

  
47
import eu.etaxonomy.cdm.hibernate.HHH_9751_Util;
48
import eu.etaxonomy.cdm.model.common.CdmBase;
49
import eu.etaxonomy.cdm.model.common.ITreeNode;
50
import eu.etaxonomy.cdm.model.common.VersionableEntity;
51
import eu.etaxonomy.cdm.model.description.CategoricalData;
52
import eu.etaxonomy.cdm.model.description.Feature;
53
import eu.etaxonomy.cdm.model.description.State;
54

  
55
/**
56
 * The class for tree nodes within a {@link FeatureTree feature tree} structure.
57
 * Feature nodes are the elementary components of such a tree since they might
58
 * be related to other nodes as a parent or as a child. A feature node belongs
59
 * at most to one feature tree. It cannot have more than one parent node but
60
 * may have several child nodes. Parent/child relations are bidirectional:
61
 * a node N1 is the parent of a node N2 if and only if the node N2 is a child of
62
 * the node N1.
63
 *
64
 * @author  m.doering
65
 * @since 08-Nov-2007 13:06:16
66
 */
67
@SuppressWarnings("serial")
68
@XmlAccessorType(XmlAccessType.FIELD)
69
@XmlType(name = "FeatureNode", propOrder = {
70
		"featureTree",
71
		"termType",
72
		"feature",
73
		"parent",
74
		"treeIndex",
75
		"sortIndex",
76
		"children",
77
		"onlyApplicableIf",
78
		"inapplicableIf"
79
})
80
@XmlRootElement(name = "FeatureNode")
81
@Entity
82
@Audited
83
@Table(name="FeatureNode", indexes = { @Index(name = "featureNodeTreeIndex", columnList = "treeIndex") })
84
public class FeatureNode <T extends DefinedTermBase> extends VersionableEntity
85
            implements ITreeNode<FeatureNode<T>>, IHasTermType, Cloneable {
86

  
87
    private static final Logger logger = Logger.getLogger(FeatureNode.class);
88

  
89
    //This is the main key a node belongs to. Although other keys may also reference
90
	//<code>this</code> node, a node usually belongs to a given key.
91
	@XmlElement(name = "FeatureTree")
92
    @XmlIDREF
93
    @XmlSchemaType(name = "IDREF")
94
    @ManyToOne(fetch = FetchType.LAZY, targetEntity=FeatureTree.class)
95
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE}) //TODO this usage is incorrect, needed only for OneToMany, check why it is here, can it be removed??
96
	 //TODO Val #3379
97
//    @NotNull
98
	private FeatureTree<T> featureTree;
99

  
100
    /**
101
     * The {@link TermType type} of this term node.
102
     * Must be the same type as for the {@link FeatureTree term collection}
103
     * this node belongs to and as the term type of the term this node links to.
104
     */
105
    @XmlAttribute(name ="TermType")
106
    @Column(name="termType")
107
    @NotNull
108
    @Type(type = "eu.etaxonomy.cdm.hibernate.EnumUserType",
109
        parameters = {@org.hibernate.annotations.Parameter(name  = "enumClass", value = "eu.etaxonomy.cdm.model.term.TermType")}
110
    )
111
    @Audited
112
    private TermType termType;
113

  
114
    @XmlElement(name = "Feature")
115
    @XmlIDREF
116
    @XmlSchemaType(name = "IDREF")
117
    @ManyToOne(fetch = FetchType.LAZY, targetEntity=DefinedTermBase.class)
118
	private T feature;
119

  
120
    @XmlElement(name = "Parent")
121
    @XmlIDREF
122
    @XmlSchemaType(name = "IDREF")
123
    @ManyToOne(fetch = FetchType.LAZY, targetEntity=FeatureNode.class)
124
    @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
125
	@JoinColumn(name="parent_id")
126
	private FeatureNode<T> parent;
127

  
128

  
129
    @XmlElement(name = "treeIndex")
130
    @Column(length=255)
131
    private String treeIndex;
132

  
133
    @XmlElementWrapper(name = "Children")
134
    @XmlElement(name = "Child")
135
    //see https://dev.e-taxonomy.eu/trac/ticket/3722
136
    @OrderColumn(name="sortIndex")
137
    @OrderBy("sortIndex")
138
	@OneToMany(fetch = FetchType.LAZY, mappedBy="parent", targetEntity=FeatureNode.class)
139
	@Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
140
	private List<FeatureNode<T>> children = new ArrayList<>();
141

  
142
    //see https://dev.e-taxonomy.eu/trac/ticket/3722
143
    private Integer sortIndex;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)