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.net.URI;
12
import java.util.Arrays;
13
import java.util.Collections;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17
import java.util.UUID;
18

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
263
    static IdentifiableSource createSource(Statement sourceStatement, ICdmRepository repo, Model model) {
264
        Resource sourceResource = model.createResource(sourceStatement.getObject().toString());
265

    
266
        String typeString = sourceResource.getProperty(OwlUtil.propSourceType).getString();
267
        IdentifiableSource source = IdentifiableSource.NewInstance(OriginalSourceType.getByKey(typeString));
268

    
269
        if(sourceResource.hasProperty(OwlUtil.propSourceIdInSource)){
270
            String idInSource = sourceResource.getProperty(OwlUtil.propSourceIdInSource).getString();
271
            source.setIdInSource(idInSource);
272
        }
273

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

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

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

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

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

    
321
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(vocabularyResource.getURI());
322
        importSource.setCitation(state.getConfig().getSourceReference());
323
        vocabulary.addSource(importSource);
324

    
325

    
326
        return vocabulary;
327
    }
328

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

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

    
340
        IdentifiableSource importSource = IdentifiableSource.NewDataImportInstance(mediaResource.getURI());
341
        importSource.setCitation(state.getConfig().getSourceReference());
342
        media.addSource(importSource);
343

    
344
        return media;
345
    }
346

    
347
    static Representation createRepresentation(ICdmRepository repo, Statement repr, Model model) {
348
        Resource repsentationResource = model.createResource(repr.getObject().toString());
349

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

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

    
367
        return representation;
368
    }
369

    
370
}
(2-2/6)