1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package eu.ehri.project.exporters.cvoc;
21
22 import com.tinkerpop.blueprints.Vertex;
23 import com.tinkerpop.frames.FramedGraph;
24 import eu.ehri.project.definitions.Ontology;
25 import eu.ehri.project.importers.cvoc.SkosRDFVocabulary;
26 import eu.ehri.project.models.UnknownProperty;
27 import eu.ehri.project.models.base.Description;
28 import eu.ehri.project.models.cvoc.Concept;
29 import eu.ehri.project.models.cvoc.Vocabulary;
30 import eu.ehri.project.utils.LanguageHelpers;
31 import org.apache.jena.rdf.model.Model;
32 import org.apache.jena.rdf.model.ModelFactory;
33 import org.apache.jena.rdf.model.Property;
34 import org.apache.jena.rdf.model.Resource;
35 import org.apache.jena.vocabulary.RDF;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 import java.io.IOException;
40 import java.io.OutputStream;
41 import java.net.URI;
42 import java.util.List;
43 import java.util.Optional;
44
45
46
47
48 public class JenaSkosExporter implements SkosExporter {
49
50 private static final Logger logger = LoggerFactory.getLogger(JenaSkosExporter.class);
51 public final static String DC_URI = "http://purl.org/dc/elements/1.1/";
52
53 private final FramedGraph<?> framedGraph;
54 private final Vocabulary vocabulary;
55 private final String format;
56
57 public JenaSkosExporter(final FramedGraph<?> framedGraph, final Vocabulary vocabulary,
58 String format) {
59 this.framedGraph = framedGraph;
60 this.vocabulary = vocabulary;
61 this.format = format;
62 }
63
64 public JenaSkosExporter(final FramedGraph<?> framedGraph, final Vocabulary vocabulary) {
65 this(framedGraph, vocabulary, null);
66 }
67
68 public JenaSkosExporter setFormat(String format) {
69 return new JenaSkosExporter(
70 framedGraph, vocabulary, format);
71 }
72
73 @Override
74 public void export(OutputStream outputStream, String base) throws IOException {
75 Model model = export(base);
76 model.getWriter(format).write(model, outputStream, null);
77 }
78
79 private String getUri(Concept concept, String baseUri) {
80 String fallback = baseUri + concept.getIdentifier();
81 String orig = concept.getProperty(Ontology.URI_KEY);
82 return Optional.ofNullable(orig).orElse(fallback);
83 }
84
85 public Model export(String base) throws IOException {
86
87 String baseUri = base == null ? SkosRDFVocabulary.DEFAULT_BASE_URI : base;
88 Iterable<Concept> concepts = vocabulary.getConcepts();
89 Model model = ModelFactory.createDefaultModel();
90 Resource skosConcept = model.createResource(SkosRDFVocabulary.CONCEPT.getURI().toString());
91 model.setNsPrefixes(SkosRDFVocabulary.NAMESPACES);
92 Property prefLabelProp = model
93 .createProperty(SkosRDFVocabulary.PREF_LABEL.getURI().toString());
94 Property inSchemeProp = model
95 .createProperty(SkosRDFVocabulary.IN_SCHEME.getURI().toString());
96 Property topConceptProp = model
97 .createProperty(SkosRDFVocabulary.HAS_TOP_CONCEPT.getURI().toString());
98
99 Resource vocabResource = model.createResource(baseUri + vocabulary.getId());
100 model.add(vocabResource, RDF.type, model
101 .createResource(SkosRDFVocabulary.CONCEPT_SCHEME.getURI().toString()));
102
103
104 for (String dcElement : new String[]{"name", "description"}) {
105 Object prop = vocabulary.getProperty(dcElement);
106 if (prop != null) {
107 writeListOrScalar(model, vocabResource,
108 model.createProperty(DC_URI + dcElement), prop, "en");
109 }
110 }
111
112 for (Concept concept : concepts) {
113 Vertex cv = concept.asVertex();
114 Resource resource = model.createResource(getUri(concept, baseUri));
115 model.add(resource, RDF.type, skosConcept);
116 model.add(resource, inSchemeProp, vocabResource);
117
118 for (String key : cv.getPropertyKeys()) {
119 writeProperty(model, resource, key, cv.getProperty(key), null);
120 }
121
122 for (Description description : concept.getDescriptions()) {
123 Vertex cdv = description.asVertex();
124 String lang = LanguageHelpers.iso639DashOneCode(description.getLanguageOfDescription());
125 model.add(resource, prefLabelProp, description.getName(), lang);
126 for (String key : cdv.getPropertyKeys()) {
127 writeProperty(model, resource, key, cdv.getProperty(key), lang);
128 }
129
130
131
132 for (UnknownProperty prop : description.getUnknownProperties()) {
133 for (String key : prop.getPropertyKeys()) {
134 String value = prop.getProperty(key);
135 if (SkosRDFVocabulary.RELATION_PROPS.containsKey(key)) {
136 model.add(resource,
137 model.createProperty(SkosRDFVocabulary.RELATION_PROPS.get(key).toString()), value);
138 }
139 }
140 }
141 }
142
143
144 if (!concept.getBroaderConcepts().iterator().hasNext()) {
145 model.add(vocabResource, topConceptProp, resource);
146 }
147
148 for (Concept other : concept.getBroaderConcepts()) {
149 Resource otherResource = model.createResource(getUri(other, baseUri));
150 model.add(resource, model.createProperty(SkosRDFVocabulary.BROADER.getURI().toString()), otherResource);
151 }
152 for (Concept other : concept.getNarrowerConcepts()) {
153 Resource otherResource = model.createResource(getUri(other, baseUri));
154 model.add(resource, model.createProperty(SkosRDFVocabulary.NARROWER.getURI().toString()), otherResource);
155 }
156 for (Concept other : concept.getRelatedConcepts()) {
157 Resource otherResource = model.createResource(getUri(other, baseUri));
158 model.add(resource, model.createProperty(SkosRDFVocabulary.RELATED.getURI().toString()), otherResource);
159 }
160 }
161 return model;
162 }
163
164 private void writeProperty(Model model, Resource resource, String key, Object property, String lang) {
165 if (SkosRDFVocabulary.LANGUAGE_PROPS.containsKey(key)) {
166
167
168
169 for (URI uri : SkosRDFVocabulary.LANGUAGE_PROPS.get(key).subList(0, 1)) {
170 writeListOrScalar(model, resource, model.createProperty(uri.toString()), property, lang);
171 }
172 } else if (SkosRDFVocabulary.GENERAL_PROPS.containsKey(key)) {
173 writeListOrScalar(model, resource,
174 model.createProperty(SkosRDFVocabulary.GENERAL_PROPS.get(key).toString()), property, null);
175 }
176 }
177
178 private void writeListOrScalar(Model model, Resource resource,
179 Property property, Object listOrScalar, String lang) {
180 if (listOrScalar instanceof List) {
181 List<?> list = (List) listOrScalar;
182 for (Object obj : list) {
183 logger.trace("Writing list property: {} -> {}", property, obj);
184 writeObject(model, resource, property, obj, lang);
185 }
186 } else {
187 logger.trace("Writing scalar property: {} -> {}", property, listOrScalar);
188 writeObject(model, resource, property, listOrScalar, lang);
189 }
190 }
191
192 private void writeObject(Model model, Resource resource,
193 Property property, Object value, String lang) {
194 if (value instanceof String) {
195 model.add(resource, property, (String) value, lang);
196 } else {
197 model.add(resource, property, model.createTypedLiteral(value));
198 }
199 }
200 }