1 package de.dlr.shepard.context.semantic;
2
3 import com.fasterxml.jackson.core.JsonProcessingException;
4 import com.fasterxml.jackson.databind.JsonNode;
5 import com.fasterxml.jackson.databind.ObjectMapper;
6 import io.quarkus.logging.Log;
7 import jakarta.ws.rs.ProcessingException;
8 import jakarta.ws.rs.client.Client;
9 import jakarta.ws.rs.client.ClientBuilder;
10 import jakarta.ws.rs.client.Invocation;
11 import jakarta.ws.rs.core.MediaType;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Optional;
16
17 public class SparqlConnector implements ISemanticRepositoryConnector {
18
19 private static final String SELECT_TEMPLATE =
20 """
21 PREFIX rdfs: <http:
22
23 SELECT DISTINCT ?o WHERE {
24 ?s rdfs:label ?o .
25 FILTER ( ?s = <%s> )
26 }""";
27
28 private static final String ASK_TEMPLATE = "ASK { ?x ?y ?z }";
29
30 private final String endpoint;
31 private final ObjectMapper mapper = new ObjectMapper();
32 private Client client = ClientBuilder.newClient();
33
34 public SparqlConnector(String endpoint) {
35 this.endpoint = endpoint;
36 }
37
38 @Override
39 public boolean healthCheck() {
40 var invocation = client
41 .target(endpoint)
42 .queryParam("query", ASK_TEMPLATE)
43 .request(MediaType.APPLICATION_JSON)
44 .buildGet();
45 String requestResult = request(invocation);
46 client.close();
47 return parseJson(requestResult).map(t -> t.get("boolean")).map(JsonNode::asBoolean).orElse(false);
48 }
49
50 @Override
51 public Map<String, String> getTerm(String termIri) {
52 var requestResult = requestTerm(termIri);
53 if (requestResult == null || requestResult.isBlank()) {
54 Log.error("Could not retrieve request result");
55 return Collections.emptyMap();
56 }
57
58 return parseResult(requestResult);
59 }
60
61 private String requestTerm(String termIri) {
62 var query = String.format(SELECT_TEMPLATE, termIri);
63 var invocation = client.target(endpoint).queryParam("query", query).request(MediaType.APPLICATION_JSON).buildGet();
64 String responseEntity = request(invocation);
65 client.close();
66 return responseEntity;
67 }
68
69 private Map<String, String> parseResult(String requestResult) {
70 var bindings = parseJson(requestResult).map(t -> t.get("results")).map(r -> r.get("bindings"));
71
72 if (bindings.isEmpty()) return Collections.emptyMap();
73
74 var result = new HashMap<String, String>();
75 for (var binding : bindings.get()) {
76 var oBinding = Optional.of(binding);
77 var object = oBinding.map(b -> b.get("o")).map(p -> p.get("value")).map(JsonNode::asText).orElse("");
78 var language = oBinding.map(b -> b.get("o")).map(p -> p.get("xml:lang")).map(JsonNode::asText).orElse("");
79 if (!object.isBlank()) result.put(language, object);
80 }
81 return result;
82 }
83
84 private Optional<JsonNode> parseJson(String string) {
85 JsonNode tree;
86 try {
87 tree = mapper.readTree(string);
88 } catch (JsonProcessingException e) {
89 return Optional.empty();
90 }
91 return Optional.of(tree);
92 }
93
94
95
96
97
98
99
100 private String request(Invocation invocation) {
101 String responseEntity;
102 try {
103 var response = invocation.invoke();
104 responseEntity = response.readEntity(String.class);
105 } catch (ProcessingException e) {
106 Log.error("Could not execute request");
107 return null;
108 }
109 return responseEntity;
110 }
111 }