Project

General

Profile

Download (19.2 KB) Statistics
| Branch: | Tag: | Revision:
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.util.Arrays;
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 org.apache.logging.log4j.LogManager;
19
import org.apache.logging.log4j.Logger;
20

    
21
import com.hp.hpl.jena.rdf.model.Model;
22
import com.hp.hpl.jena.rdf.model.Resource;
23
import com.hp.hpl.jena.rdf.model.Statement;
24

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

    
47
/**
48
 * @author pplitzner
49
 * @since May 26, 2019
50
 */
51
public class OwlImportUtil {
52

    
53
    private final static Logger logger = LogManager.getLogger();
54

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

    
112
    static void addCharacterProperties(Character character, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
113
        addFeatureProperties(character, termResource, repo, model, state);
114
        // import property
115
        if(character.getProperty()!=null){
116
            Statement propertyStatement = termResource.getProperty(OwlUtil.propCharacterHasProperty);
117
            Resource propertyResource = model.createResource(propertyStatement.getObject().toString());
118
            TermNode propertyNode = loadNode(propertyResource, repo, model, state);
119
            if(propertyNode!=null){
120
                character.setProperty(propertyNode);
121
            }
122
            else{
123
                logger.error("Property not found for character: "+character);
124
                return;
125
            }
126
        }
127
        // import structure
128
        if(character.getStructure()!=null){
129
            Statement structureStatement = termResource.getProperty(OwlUtil.propCharacterHasStructure);
130
            Resource structureResource = model.createResource(structureStatement.getObject().toString());
131
            TermNode structureNode = loadNode(structureResource, repo, model, state);
132
            if(structureNode!=null){
133
                character.setStructure(structureNode);
134
            }
135
            else{
136
                logger.error("Structure not found for character: "+character);
137
                return;
138
            }
139
        }
140
        // import structure modifier
141
        if(character.getStructureModifier()!=null && termResource.hasProperty(OwlUtil.propCharacterHasStructureModfier)){
142
            Statement structureModifierStatement = termResource.getProperty(OwlUtil.propCharacterHasStructureModfier);
143
            Resource structureModifierResource = model.createResource(structureModifierStatement.getObject().toString());
144
            DefinedTerm structureModifier = findTerm(DefinedTerm.class, structureModifierResource, repo, model, state);
145
            character.setStructureModifier(structureModifier);
146
        }
147
    }
148

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

    
152
        // term URI
153
        String uriString = termResource.hasProperty(OwlUtil.propUri)?termResource.getProperty(OwlUtil.propUri).getString():null;
154
        if(CdmUtils.isNotBlank(uriString)){
155
            term.setUri(URI.create(uriString));
156
        }
157
        // symbol
158
        String symbolString = termResource.hasProperty(OwlUtil.propTermSymbol)?termResource.getProperty(OwlUtil.propTermSymbol).getString():null;
159
        if(CdmUtils.isNotBlank(symbolString)){
160
            term.setSymbol(symbolString);
161
        }
162
        // symbol2
163
        String symbol2String = termResource.hasProperty(OwlUtil.propTermSymbol2)?termResource.getProperty(OwlUtil.propTermSymbol2).getString():null;
164
        if(CdmUtils.isNotBlank(symbol2String)){
165
            term.setSymbol2(symbol2String);
166
        }
167
        // idInVocabulary
168
        String idInVocabularyString = termResource.hasProperty(OwlUtil.propTermIdInVocabulary)?termResource.getProperty(OwlUtil.propTermIdInVocabulary).getString():null;
169
        if(CdmUtils.isNotBlank(idInVocabularyString)){
170
            term.setIdInVocabulary(idInVocabularyString);
171
        }
172

    
173
        // import representations
174
        Set<Representation> representations = new HashSet<>();
175
        termResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->representations.add(OwlImportUtil.createRepresentation(repo, r, model)));
176
        if(representations.isEmpty()){
177
            logger.error("No representations found for term: "+termResource.getProperty(OwlUtil.propUuid));
178
        }
179
        representations.forEach(rep->term.addRepresentation(rep));
180

    
181
        // import sources
182
        Set<IdentifiableSource> sources = new HashSet<>();
183
        termResource.listProperties(OwlUtil.propTermHasSource).forEachRemaining(sourceStatement->sources.add(OwlImportUtil.createSource(sourceStatement, repo, model)));
184
        sources.forEach(source->term.addSource(source));
185

    
186
        // add import source
187
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(termResource.getURI());
188
        importSource.setCitation(state.getConfig().getSourceReference());
189
        term.addSource(importSource);
190
    }
191

    
192
    static <T extends DefinedTermBase> T findTerm(Class<T> clazz, Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
193
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
194
        List<T> terms = repo.getTermService().find(clazz, Collections.singleton(termUuid));
195
        if(!terms.isEmpty()){
196
            return terms.iterator().next();
197
        }
198
        return null;
199
    }
200

    
201
    private static TermVocabulary findVocabulary(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
202
        UUID termUuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
203
        return repo.getVocabularyService().find(termUuid);
204
    }
205

    
206
    private static TermNode loadNode(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
207
        UUID uuid = UUID.fromString(termResource.getProperty(OwlUtil.propUuid).getString());
208
        return repo.getTermNodeService().load(uuid, Arrays.asList(new String[]{"term"}) );
209
    }
210

    
211
    private static Reference findReference(Resource resource, ICdmRepository repo){
212
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
213
        return repo.getReferenceService().find(uuid);
214
    }
215

    
216
    static Media findMedia(Resource resource, ICdmRepository repo){
217
        UUID uuid = UUID.fromString(resource.getProperty(OwlUtil.propUuid).getString());
218
        return repo.getMediaService().find(uuid);
219
    }
220

    
221
    static Feature createFeature(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
222
        Feature feature = findTerm(Feature.class, termResource, repo, model, state);
223
        if(feature==null){
224
            feature = Feature.NewInstance();
225
            addFeatureProperties(feature, termResource, repo, model, state);
226
        }
227
        return feature;
228
    }
229

    
230
    static State createState(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
231
        State stateTerm = findTerm(State.class, termResource, repo, model, state);
232
        if(stateTerm==null){
233
            stateTerm = State.NewInstance();
234
        }
235
        return stateTerm;
236
    }
237

    
238
    private static Character createCharacter(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
239
        Character character = findTerm(Character.class, termResource, repo, model, state);
240
        if(character==null){
241
            character = Character.NewInstance();
242
        }
243
        return character;
244
    }
245

    
246
    static DefinedTermBase createTerm(Resource termResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
247
        TermType termType = TermType.getByKey(termResource.getProperty(OwlUtil.propType).getString());
248
        DefinedTermBase term = null;
249
        // create new term
250
        if(termType.equals(TermType.Feature)){
251
            term = createFeature(termResource, repo, model, state);
252
        }
253
        else if(termType.equals(TermType.State)){
254
            term = createState(termResource, repo, model, state);
255
        }
256
        else if(termType.equals(TermType.Character)){
257
            term = createCharacter(termResource, repo, model, state);
258
        }
259
        else{
260
            term = DefinedTerm.NewInstance(termType);
261
        }
262
        addTermProperties(term, termResource, repo, model, state);
263
        return term;
264
    }
265

    
266
    static IdentifiableSource createSource(Statement sourceStatement, ICdmRepository repo, Model model) {
267
        Resource sourceResource = model.createResource(sourceStatement.getObject().toString());
268

    
269
        String typeString = sourceResource.getProperty(OwlUtil.propSourceType).getString();
270
        IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.getByKey(typeString));
271

    
272
        if(sourceResource.hasProperty(OwlUtil.propSourceIdInSource)){
273
            String idInSource = sourceResource.getProperty(OwlUtil.propSourceIdInSource).getString();
274
            source.setIdInSource(idInSource);
275
        }
276

    
277
        // import citation
278
        List<Statement> citationStatements = sourceResource.listProperties(OwlUtil.propSourceHasCitation).toList();
279
        if(citationStatements.size()>1){
280
            logger.error("More than one citations found for source. Choosing one arbitrarily. - "+sourceResource.toString());
281
        }
282
        if(!citationStatements.isEmpty()){
283
            Statement citationStatement = citationStatements.iterator().next();
284
            Resource citationResource = model.createResource(citationStatement.getObject().toString());
285
            Reference reference = findReference(citationResource, repo);
286
            if(reference==null){
287
                reference = createReference(citationResource, model);
288
            }
289
            source.setCitation(reference);
290
        }
291
        return source;
292
    }
293

    
294
    static Reference createReference(Resource citationResource, Model model){
295
        String titleString = citationResource.getProperty(OwlUtil.propReferenceTitle).getString();
296
        Reference citation = ReferenceFactory.newGeneric();
297
        // FIXME setting the UUID leads to org.hibernate.NonUniqueObjectException:
298
        // A different object with the same identifier value was already associated with the session : [eu.etaxonomy.cdm.model.reference.Reference#12]
299
//        citation.setUuid(UUID.fromString(citationResource.getProperty(OwlUtil.propUuid).getString()));
300
        citation.setTitle(titleString);
301
        return citation;
302
    }
303

    
304
    static TermVocabulary createVocabulary(Resource vocabularyResource, ICdmRepository repo, Model model, StructureTreeOwlImportState state){
305
        TermType termType = TermType.getByKey(vocabularyResource.getProperty(OwlUtil.propType).getString());
306
        // create new vocabulary
307
        TermVocabulary vocabulary = TermVocabulary.NewInstance(termType);
308
        vocabulary.setUuid(UUID.fromString(vocabularyResource.getProperty(OwlUtil.propUuid).getString()));
309

    
310
        // voc URI
311
        String vocUriString = vocabularyResource.hasProperty(OwlUtil.propUri)?vocabularyResource.getProperty(OwlUtil.propUri).getString():null;
312
        if(CdmUtils.isNotBlank(vocUriString)){
313
            vocabulary.setUri(URI.create(vocUriString));
314
        }
315

    
316
        // voc representations
317
        Set<Representation> vocRepresentations = new HashSet<>();
318
        vocabularyResource.listProperties(OwlUtil.propHasRepresentation).forEachRemaining(r->vocRepresentations.add(OwlImportUtil.createRepresentation(repo, r, model)));
319
        if(vocRepresentations.isEmpty()){
320
            logger.error("No representations found for vocabulary: "+vocabularyResource.getProperty(OwlUtil.propUuid));
321
        }
322
        vocRepresentations.forEach(rep->vocabulary.addRepresentation(rep));
323

    
324
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(vocabularyResource.getURI());
325
        importSource.setCitation(state.getConfig().getSourceReference());
326
        vocabulary.addSource(importSource);
327

    
328

    
329
        return vocabulary;
330
    }
331

    
332
    static Media createMedia(Resource mediaResource, StructureTreeOwlImportState state){
333
        URI mediaUri = URI.create(mediaResource.getProperty(OwlUtil.propMediaUri).getString());
334
        // create new media
335
        Media media = Media.NewInstance(mediaUri, null, null, null);
336
        media.setUuid(UUID.fromString(mediaResource.getProperty(OwlUtil.propUuid).getString()));
337

    
338
        if(mediaResource.hasProperty(OwlUtil.propMediaTitle)){
339
            // TODO: support multiple language titles
340
            media.putTitle(Language.DEFAULT(), mediaResource.getProperty(OwlUtil.propMediaTitle).getString());
341
        }
342

    
343
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(mediaResource.getURI());
344
        importSource.setCitation(state.getConfig().getSourceReference());
345
        media.addSource(importSource);
346

    
347
        return media;
348
    }
349

    
350
    static Representation createRepresentation(ICdmRepository repo, Statement repr, Model model) {
351
        Resource repsentationResource = model.createResource(repr.getObject().toString());
352

    
353
        String languageLabel = repsentationResource.getProperty(OwlUtil.propLanguage).getString();
354
        UUID languageUuid = UUID.fromString(repsentationResource.getProperty(OwlUtil.propLanguageUuid).getString());
355
        Language language = Language.getLanguageFromUuid(languageUuid);
356
        if(language==null){
357
            language = repo.getTermService().getLanguageByLabel(languageLabel);
358
        }
359
        if(language==null){
360
            language = Language.getDefaultLanguage();
361
        }
362

    
363
        String abbreviatedLabel = repsentationResource.hasProperty(OwlUtil.propLabelAbbrev)?repsentationResource.getProperty(OwlUtil.propLabelAbbrev).getString():null;
364
        String plural = repsentationResource.hasProperty(OwlUtil.propLabelPlural)?repsentationResource.getProperty(OwlUtil.propLabelPlural).getString():null;
365
        String label = repsentationResource.getProperty(OwlUtil.propLabel).getString();
366
        String description = repsentationResource.hasProperty(OwlUtil.propDescription)?repsentationResource.getProperty(OwlUtil.propDescription).getString():null;
367
        Representation representation = Representation.NewInstance(description, label, abbreviatedLabel, language);
368
        representation.setPlural(plural);
369

    
370
        return representation;
371
    }
372

    
373
}
(2-2/6)