1 package de.dlr.shepard.common.search.services;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertThrows;
5
6 import de.dlr.shepard.auth.security.AuthenticationContext;
7 import de.dlr.shepard.auth.security.JWTPrincipal;
8 import de.dlr.shepard.auth.users.entities.User;
9 import de.dlr.shepard.auth.users.services.UserService;
10 import de.dlr.shepard.common.exceptions.ShepardParserException;
11 import de.dlr.shepard.common.search.io.ResponseBody;
12 import de.dlr.shepard.common.search.io.SearchBody;
13 import de.dlr.shepard.common.search.io.SearchParams;
14 import de.dlr.shepard.common.search.io.SearchScope;
15 import de.dlr.shepard.common.util.TraversalRules;
16 import de.dlr.shepard.context.collection.entities.Collection;
17 import de.dlr.shepard.context.collection.entities.DataObject;
18 import de.dlr.shepard.context.collection.io.CollectionIO;
19 import de.dlr.shepard.context.collection.io.DataObjectIO;
20 import de.dlr.shepard.context.collection.services.CollectionService;
21 import de.dlr.shepard.context.collection.services.DataObjectService;
22 import de.dlr.shepard.context.references.timeseriesreference.io.TimeseriesReferenceIO;
23 import de.dlr.shepard.context.references.timeseriesreference.model.TimeseriesReference;
24 import de.dlr.shepard.context.references.timeseriesreference.services.TimeseriesReferenceService;
25 import de.dlr.shepard.context.semantic.SemanticRepositoryType;
26 import de.dlr.shepard.context.semantic.entities.SemanticRepository;
27 import de.dlr.shepard.context.semantic.io.SemanticAnnotationIO;
28 import de.dlr.shepard.context.semantic.io.SemanticRepositoryIO;
29 import de.dlr.shepard.context.semantic.services.AnnotatableTimeseriesService;
30 import de.dlr.shepard.context.semantic.services.SemanticAnnotationService;
31 import de.dlr.shepard.context.semantic.services.SemanticRepositoryService;
32 import de.dlr.shepard.data.timeseries.io.TimeseriesContainerIO;
33 import de.dlr.shepard.data.timeseries.model.Timeseries;
34 import de.dlr.shepard.data.timeseries.model.TimeseriesContainer;
35 import de.dlr.shepard.data.timeseries.model.TimeseriesDataPoint;
36 import de.dlr.shepard.data.timeseries.model.TimeseriesEntity;
37 import de.dlr.shepard.data.timeseries.services.TimeseriesContainerService;
38 import de.dlr.shepard.data.timeseries.services.TimeseriesService;
39 import de.dlr.shepard.integrationtests.WireMockResource;
40 import io.quarkus.test.common.WithTestResource;
41 import io.quarkus.test.junit.QuarkusTest;
42 import jakarta.inject.Inject;
43 import jakarta.transaction.Transactional;
44 import java.util.ArrayList;
45 import java.util.List;
46 import org.junit.jupiter.api.BeforeEach;
47 import org.junit.jupiter.api.Test;
48
49 @QuarkusTest
50 @WithTestResource(WireMockResource.class)
51 public class ReferenceSearchServiceQuarkusTest {
52
53 @Inject
54 CollectionService collectionService;
55
56 @Inject
57 DataObjectService dataObjectService;
58
59 @Inject
60 ReferenceSearchService referenceSearcher;
61
62 @Inject
63 TimeseriesReferenceService timeseriesReferenceService;
64
65 @Inject
66 TimeseriesService timeseriesService;
67
68 @Inject
69 AnnotatableTimeseriesService annotatableTimeseriesService;
70
71 @Inject
72 SemanticRepositoryService semanticRepositoryService;
73
74 @Inject
75 TimeseriesContainerService timeseriesContainerService;
76
77 @Inject
78 AuthenticationContext authenticationContext;
79
80 @Inject
81 UserService userService;
82
83 @Inject
84 SemanticAnnotationService semanticAnnotationService;
85
86 private static Collection collection1;
87 private static DataObject dataObjectc1d1;
88 private static TimeseriesReference annoReference;
89 private static TimeseriesReference noAnnoReference;
90 private static TimeseriesContainer tsCon;
91 private static TimeseriesEntity timeseriesEntity1;
92 private static TimeseriesEntity timeseriesEntity2;
93 private static SemanticRepository repository;
94 private static User user;
95 private static SemanticAnnotationIO AnnoToCreate;
96 private static String username = "username";
97 private static SearchScope scope;
98 private static SearchBody body;
99 private static SearchParams params;
100 private static String query;
101 private static ResponseBody response;
102
103 @BeforeEach
104 public void setUp() {
105
106 if (user == null) {
107 User user = new User(username);
108 userService.createOrUpdateUser(user);
109 authenticationContext.setPrincipal(new JWTPrincipal(username, "key"));
110 }
111
112 if (collection1 == null) {
113 CollectionIO collection1IO = new CollectionIO();
114 collection1IO.setName("collection1" + System.currentTimeMillis());
115 collection1 = collectionService.createCollection(collection1IO);
116 }
117
118 if (dataObjectc1d1 == null) {
119 DataObjectIO dataObjectc1d1IO = new DataObjectIO();
120 dataObjectc1d1IO.setName("c1do1" + System.currentTimeMillis());
121 dataObjectc1d1 = dataObjectService.createDataObject(collection1.getShepardId(), dataObjectc1d1IO);
122 }
123
124 if (tsCon == null) {
125
126 TimeseriesContainerIO tsConIO = new TimeseriesContainerIO();
127 tsConIO.setName("container");
128 tsCon = timeseriesContainerService.createContainer(tsConIO);
129
130 TimeseriesDataPoint dataPoint = new TimeseriesDataPoint(4l, true);
131 List<TimeseriesDataPoint> points = new ArrayList<TimeseriesDataPoint>();
132 points.add(dataPoint);
133 Timeseries ts1 = new Timeseries("m1", "d1", "l1", "s1", "f1");
134 Timeseries ts2 = new Timeseries("m2", "d2", "l2", "s2", "f2");
135 timeseriesEntity1 = timeseriesService.saveDataPoints(tsCon.getId(), ts1, points);
136 timeseriesEntity2 = timeseriesService.saveDataPoints(tsCon.getId(), ts2, points);
137
138 SemanticRepositoryIO repToCreate = new SemanticRepositoryIO();
139 repToCreate.setName("SemanticRepository");
140 repToCreate.setType(SemanticRepositoryType.SPARQL);
141 repToCreate.setEndpoint(WireMockResource.getWireMockServerURlWithPath("/sparql"));
142 repository = semanticRepositoryService.createRepository(repToCreate);
143
144 TimeseriesReferenceIO ref1IO = new TimeseriesReferenceIO();
145 ref1IO.setName("refAnno");
146 ref1IO.setStart(0l);
147 ref1IO.setEnd(9l);
148 List<Timeseries> timeseries1 = new ArrayList<Timeseries>();
149 timeseries1.add(ts1);
150 ref1IO.setTimeseries(timeseries1);
151 ref1IO.setTimeseriesContainerId(tsCon.getId());
152 annoReference = timeseriesReferenceService.createReference(
153 collection1.getShepardId(),
154 dataObjectc1d1.getShepardId(),
155 ref1IO
156 );
157
158 TimeseriesReferenceIO ref2IO = new TimeseriesReferenceIO();
159 ref2IO.setName("refWithoutAnno");
160 ref2IO.setStart(0l);
161 ref2IO.setEnd(9l);
162 List<Timeseries> timeseries2 = new ArrayList<Timeseries>();
163 timeseries2.add(ts2);
164 ref2IO.setTimeseries(timeseries2);
165 ref2IO.setTimeseriesContainerId(tsCon.getId());
166 annoReference = timeseriesReferenceService.createReference(
167 collection1.getShepardId(),
168 dataObjectc1d1.getShepardId(),
169 ref2IO
170 );
171 }
172 if (AnnoToCreate == null) {
173 AnnoToCreate = new SemanticAnnotationIO();
174 AnnoToCreate.setPropertyIRI("http://dbpedia.org/ontology/ingredient");
175 AnnoToCreate.setPropertyRepositoryId(repository.getId());
176 AnnoToCreate.setValueIRI("http://dbpedia.org/resource/Almond_milk");
177 AnnoToCreate.setValueRepositoryId(repository.getId());
178 semanticAnnotationService.createAnnotationByShepardId(annoReference.getId(), AnnoToCreate);
179 }
180 if (scope == null) scope = new SearchScope();
181 if (body == null) {
182 body = new SearchBody();
183 TraversalRules[] rules = {};
184 scope.setTraversalRules(rules);
185 }
186 if (params == null) params = new SearchParams();
187 }
188
189 @Test
190 @Transactional
191 public void findNoReference() {
192 scope.setCollectionId(collection1.getShepardId());
193 scope.setDataObjectId(dataObjectc1d1.getShepardId());
194 SearchScope[] scopes = { scope };
195 query = "{\"property\": \"hasAnnotation\", \"value\": \"ingre.*::Almon.*\", \"operator\": \"eq\"}";
196 params.setQuery(query);
197 body.setSearchParams(params);
198 body.setScopes(scopes);
199 response = referenceSearcher.search(body);
200 assertEquals(0, response.getResults().length);
201 }
202
203 @Test
204 @Transactional
205 public void findExactlyOneReferenceByeIRIEquality() {
206 scope.setCollectionId(collection1.getShepardId());
207 scope.setDataObjectId(dataObjectc1d1.getShepardId());
208 SearchScope[] scopes = { scope };
209 query =
210 "{\"property\": \"hasAnnotationIRI\", \"value\": \"http://dbpedia.org/ontology/ingredient::http://dbpedia.org/resource/Almond_milk\", \"operator\": \"eq\"}";
211 params.setQuery(query);
212 body.setSearchParams(params);
213 body.setScopes(scopes);
214 response = referenceSearcher.search(body);
215 assertEquals(1, response.getResults().length);
216 assertEquals(annoReference.getId(), response.getResultSet()[0].getReferenceId());
217 }
218
219 @Test
220 @Transactional
221 public void findByPropertyIRIContains() {
222 scope.setCollectionId(collection1.getShepardId());
223 scope.setDataObjectId(dataObjectc1d1.getShepardId());
224 SearchScope[] scopes = { scope };
225 query = "{\"property\": \"propertyIRI\", \"value\": \"dbpedia\", \"operator\": \"contains\"}";
226 params.setQuery(query);
227 body.setSearchParams(params);
228 body.setScopes(scopes);
229 response = referenceSearcher.search(body);
230 assertEquals(true, response.getResults().length > 0);
231
232 }
233
234 @Test
235 @Transactional
236 public void findByValueIRIContains() {
237 scope.setCollectionId(collection1.getShepardId());
238 scope.setDataObjectId(dataObjectc1d1.getShepardId());
239 SearchScope[] scopes = { scope };
240 query = "{\"property\": \"valueIRI\", \"value\": \"Almond\", \"operator\": \"contains\"}";
241 params.setQuery(query);
242 body.setSearchParams(params);
243 body.setScopes(scopes);
244 response = referenceSearcher.search(body);
245 assertEquals(true, response.getResults().length > 0);
246
247 }
248
249 @Test
250 @Transactional
251 public void findExactlyOneReferenceByeAnnotationRegMatch() {
252 scope.setCollectionId(collection1.getShepardId());
253 scope.setDataObjectId(dataObjectc1d1.getShepardId());
254 SearchScope[] scopes = { scope };
255 query = "{\"property\": \"hasAnnotation\", \"value\": \"ingre.*::Almon.*\", \"operator\": \"regmatch\"}";
256 body.setScopes(scopes);
257 params.setQuery(query);
258 body.setSearchParams(params);
259 ResponseBody response = referenceSearcher.search(body);
260 assertEquals(1, response.getResults().length);
261 assertEquals(annoReference.getId(), response.getResultSet()[0].getReferenceId());
262 }
263
264 @Test
265 @Transactional
266 public void provokeExceptionByInvalidAnnotationIRI() {
267 scope.setCollectionId(collection1.getShepardId());
268 scope.setDataObjectId(dataObjectc1d1.getShepardId());
269 TraversalRules[] rules = {};
270 scope.setTraversalRules(rules);
271 SearchScope[] scopes = { scope };
272 String wrongAnnotation = "http://dbpedia.org/ontology/ingredienthttp://dbpedia.org/resource/Almond_milk";
273 query = "{\"property\": \"hasAnnotationIRI\", \"value\": \"" + wrongAnnotation + "\", \"operator\": \"eq\"}";
274 body.setScopes(scopes);
275 SearchParams params = new SearchParams();
276 params.setQuery(query);
277 body.setSearchParams(params);
278 assertThrows(ShepardParserException.class, () -> referenceSearcher.search(body));
279 }
280
281 @Test
282 @Transactional
283 public void provokeExceptionByTooManyDoubleColons() {
284 scope.setCollectionId(collection1.getShepardId());
285 scope.setDataObjectId(dataObjectc1d1.getShepardId());
286 TraversalRules[] rules = {};
287 scope.setTraversalRules(rules);
288 SearchScope[] scopes = { scope };
289 String wrongAnnotation = "::B::";
290 query = "{\"property\": \"hasAnnotationIRI\", \"value\": \"" + wrongAnnotation + "\", \"operator\": \"eq\"}";
291 body.setScopes(scopes);
292 SearchParams params = new SearchParams();
293 params.setQuery(query);
294 body.setSearchParams(params);
295 assertThrows(ShepardParserException.class, () -> referenceSearcher.search(body));
296 }
297
298 @Test
299 @Transactional
300 public void provokeExceptionByThreeConsecutiveColons() {
301 scope.setCollectionId(collection1.getShepardId());
302 scope.setDataObjectId(dataObjectc1d1.getShepardId());
303 TraversalRules[] rules = {};
304 scope.setTraversalRules(rules);
305 SearchScope[] scopes = { scope };
306 String wrongAnnotation = ":::";
307 query = "{\"property\": \"hasAnnotationIRI\", \"value\": \"" + wrongAnnotation + "\", \"operator\": \"eq\"}";
308 body.setScopes(scopes);
309 SearchParams params = new SearchParams();
310 params.setQuery(query);
311 body.setSearchParams(params);
312 assertThrows(ShepardParserException.class, () -> referenceSearcher.search(body));
313 }
314 }