View Javadoc
1   package de.dlr.shepard.integrationtests;
2   
3   import static io.restassured.RestAssured.given;
4   import static org.assertj.core.api.Assertions.assertThat;
5   
6   import de.dlr.shepard.auth.permission.io.PermissionsIO;
7   import de.dlr.shepard.auth.users.io.UserGroupIO;
8   import de.dlr.shepard.common.search.io.QueryType;
9   import de.dlr.shepard.common.search.io.ResponseBody;
10  import de.dlr.shepard.common.search.io.ResultTriple;
11  import de.dlr.shepard.common.search.io.SearchBody;
12  import de.dlr.shepard.common.search.io.SearchParams;
13  import de.dlr.shepard.common.search.io.SearchScope;
14  import de.dlr.shepard.common.util.Constants;
15  import de.dlr.shepard.common.util.TraversalRules;
16  import de.dlr.shepard.context.collection.io.CollectionIO;
17  import de.dlr.shepard.context.semantic.SemanticRepositoryType;
18  import de.dlr.shepard.context.semantic.io.SemanticAnnotationIO;
19  import de.dlr.shepard.context.semantic.io.SemanticRepositoryIO;
20  import io.quarkus.test.common.WithTestResource;
21  import io.quarkus.test.junit.QuarkusIntegrationTest;
22  import java.util.Map;
23  import org.junit.jupiter.api.BeforeAll;
24  import org.junit.jupiter.api.MethodOrderer;
25  import org.junit.jupiter.api.Order;
26  import org.junit.jupiter.api.Test;
27  import org.junit.jupiter.api.TestMethodOrder;
28  
29  @QuarkusIntegrationTest
30  @WithTestResource(WireMockResource.class)
31  @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
32  public class CollectionSearcherIT extends BaseTestCaseIT {
33  
34    private static String collectionsURL;
35    private static CollectionIO collection1;
36    private static CollectionIO collection2;
37    private static String searchURL;
38  
39    private static String repositoryURL;
40    private static SemanticRepositoryIO repository;
41    private static SemanticAnnotationIO annotation;
42    private static CollectionIO annotatedCollection;
43    private static String annotatedCollectionURL;
44  
45    @BeforeAll
46    public static void setUp() {
47      collectionsURL = "/" + Constants.COLLECTIONS;
48  
49      var payload1 = new CollectionIO();
50      payload1.setName("CollectionDummy");
51      payload1.setDescription("First Collection");
52      payload1.setAttributes(Map.of("a", "1", "b", "2"));
53      collection1 = given()
54        .spec(requestSpecOfDefaultUser)
55        .body(payload1)
56        .when()
57        .post(collectionsURL)
58        .then()
59        .statusCode(201)
60        .extract()
61        .as(CollectionIO.class);
62      var payload2 = new CollectionIO();
63      payload2.setName("secondCollectionDummy");
64      payload2.setDescription("Second Collection");
65      collection2 = given()
66        .spec(requestSpecOfDefaultUser)
67        .body(payload2)
68        .when()
69        .post(collectionsURL)
70        .then()
71        .statusCode(201)
72        .extract()
73        .as(CollectionIO.class);
74      searchURL = "/" + Constants.SEARCH;
75  
76      // for search involving SemanticAnnotations
77      repositoryURL = "/" + Constants.SEMANTIC_REPOSITORIES;
78      annotatedCollection = createCollection("SemanticsCollection");
79      annotatedCollectionURL = "/%s/%d/semanticAnnotations".formatted(Constants.COLLECTIONS, annotatedCollection.getId());
80      var repositoryToCreate = new SemanticRepositoryIO();
81      repositoryToCreate.setName("SemanticRepository");
82      repositoryToCreate.setType(SemanticRepositoryType.SPARQL);
83      repositoryToCreate.setEndpoint(WireMockResource.getWireMockServerURlWithPath("/sparql"));
84      repository = given()
85        .spec(requestSpecOfDefaultUser)
86        .body(repositoryToCreate)
87        .when()
88        .post(repositoryURL)
89        .then()
90        .statusCode(201)
91        .extract()
92        .as(SemanticRepositoryIO.class);
93  
94      var annotationToCreate = new SemanticAnnotationIO();
95      annotationToCreate.setPropertyIRI("http://dbpedia.org/ontology/ingredient");
96      annotationToCreate.setPropertyRepositoryId(repository.getId());
97      annotationToCreate.setValueIRI("http://dbpedia.org/resource/Almond_milk");
98      annotationToCreate.setValueRepositoryId(repository.getId());
99      annotation = given()
100       .spec(requestSpecOfDefaultUser)
101       .body(annotationToCreate)
102       .when()
103       .post(annotatedCollectionURL)
104       .then()
105       .statusCode(201)
106       .extract()
107       .as(SemanticAnnotationIO.class);
108   }
109 
110   @Test
111   @Order(1)
112   public void findOneOutOfTwoCollectionsTest() {
113     SearchBody searchBody = new SearchBody();
114     SearchScope searchScope = new SearchScope();
115     searchScope.setTraversalRules(new TraversalRules[] {});
116     searchBody.setScopes(new SearchScope[] { searchScope });
117     SearchParams searchParams = new SearchParams();
118     searchParams.setQueryType(QueryType.Collection);
119     String query =
120       """
121       {
122         "OR": [
123           {
124             "property": "id",
125             "value": %d,
126             "operator": "eq"
127           },
128           {
129             "property": "number",
130             "value": 123,
131             "operator": "le"
132           }
133       ]}""".formatted(collection1.getId());
134     searchParams.setQuery(query);
135     searchBody.setSearchParams(searchParams);
136     var result = given()
137       .spec(requestSpecOfDefaultUser)
138       .body(searchBody)
139       .when()
140       .post(searchURL)
141       .then()
142       .statusCode(200)
143       .extract()
144       .as(ResponseBody.class);
145     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
146     assertThat(result.getResultSet()).containsExactly(triple1);
147     assertThat(result.getResults()[0].getId()).isEqualTo(collection1.getId());
148     assertThat(result.getSearchParams()).isEqualTo(searchParams);
149   }
150 
151   @Test
152   @Order(2)
153   public void findCollectionByAttribute() {
154     SearchBody searchBody = new SearchBody();
155     SearchScope searchScope = new SearchScope();
156     searchScope.setTraversalRules(new TraversalRules[] {});
157     searchBody.setScopes(new SearchScope[] { searchScope });
158     SearchParams searchParams = new SearchParams();
159     searchParams.setQueryType(QueryType.Collection);
160     String query =
161       """
162       {
163         "AND": [
164           {
165             "property": "id",
166             "value": %d,
167             "operator": "eq"
168           },
169           {
170             "property": "attributes.a",
171             "value": "1",
172             "operator": "eq"
173           }
174         ]
175       }""".formatted(collection1.getId());
176     searchParams.setQuery(query);
177     searchBody.setSearchParams(searchParams);
178     var result = given()
179       .spec(requestSpecOfDefaultUser)
180       .body(searchBody)
181       .when()
182       .post(searchURL)
183       .then()
184       .statusCode(200)
185       .extract()
186       .as(ResponseBody.class);
187     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
188     assertThat(result.getResultSet()).containsExactly(triple1);
189     assertThat(result.getResults()[0].getId()).isEqualTo(collection1.getId());
190     assertThat(result.getSearchParams()).isEqualTo(searchParams);
191   }
192 
193   @Test
194   @Order(3)
195   public void neTest() {
196     SearchBody searchBody = new SearchBody();
197     SearchScope searchScope = new SearchScope();
198     searchScope.setTraversalRules(new TraversalRules[] {});
199     searchBody.setScopes(new SearchScope[] { searchScope });
200     SearchParams searchParams = new SearchParams();
201     searchParams.setQueryType(QueryType.Collection);
202     String query =
203       """
204       {
205         "property": "id",
206         "value": %d,
207         "operator": "ne"
208       }""".formatted(collection1.getId());
209     searchParams.setQuery(query);
210     searchBody.setSearchParams(searchParams);
211     var result = given()
212       .spec(requestSpecOfDefaultUser)
213       .body(searchBody)
214       .when()
215       .post(searchURL)
216       .then()
217       .statusCode(200)
218       .extract()
219       .as(ResponseBody.class);
220     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
221     assertThat(result.getResultSet()).doesNotContain(triple1);
222   }
223 
224   @Test
225   @Order(4)
226   public void findTwoOutOfTwoCollectionsTest() {
227     SearchBody searchBody = new SearchBody();
228     SearchScope searchScope = new SearchScope();
229     searchScope.setTraversalRules(new TraversalRules[] {});
230     searchBody.setScopes(new SearchScope[] { searchScope });
231     SearchParams searchParams = new SearchParams();
232     searchParams.setQueryType(QueryType.Collection);
233     String query =
234       """
235       {
236         "OR": [
237           {
238             "property": "id",
239             "value": %d,
240             "operator": "ge"
241           },
242           {
243             "property": "id",
244             "value": %d,
245             "operator": "le"
246           }
247       ]}""".formatted(collection1.getId(), collection2.getId());
248     searchParams.setQuery(query);
249     searchBody.setSearchParams(searchParams);
250     var result = given()
251       .spec(requestSpecOfDefaultUser)
252       .body(searchBody)
253       .when()
254       .post(searchURL)
255       .then()
256       .statusCode(200)
257       .extract()
258       .as(ResponseBody.class);
259     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
260     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
261     assertThat(result.getResultSet()).contains(triple1, triple2);
262   }
263 
264   @Test
265   @Order(5)
266   public void findNoCollectionTest() {
267     SearchBody searchBody = new SearchBody();
268     SearchScope searchScope = new SearchScope();
269     searchScope.setTraversalRules(new TraversalRules[] {});
270     searchBody.setScopes(new SearchScope[] { searchScope });
271     SearchParams searchParams = new SearchParams();
272     searchParams.setQueryType(QueryType.Collection);
273     String query =
274       """
275       {
276         "AND": [
277           {
278             "property": "id",
279             "value": %d,
280             "operator": "gt"
281           },
282           {
283             "property": "id",
284             "value": %d,
285             "operator": "gt"
286           }
287       ]}""".formatted(collection1.getId(), collection2.getId());
288     searchParams.setQuery(query);
289     searchBody.setSearchParams(searchParams);
290     var result = given()
291       .spec(requestSpecOfDefaultUser)
292       .body(searchBody)
293       .when()
294       .post(searchURL)
295       .then()
296       .statusCode(200)
297       .extract()
298       .as(ResponseBody.class);
299     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
300     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
301     assertThat(result.getResultSet()).doesNotContain(triple1, triple2);
302   }
303 
304   @Test
305   @Order(6)
306   public void findByAndTest() {
307     SearchBody searchBody = new SearchBody();
308     SearchScope searchScope = new SearchScope();
309     searchScope.setTraversalRules(new TraversalRules[] {});
310     searchBody.setScopes(new SearchScope[] { searchScope });
311     SearchParams searchParams = new SearchParams();
312     searchParams.setQueryType(QueryType.Collection);
313     String query =
314       """
315       {
316         "AND": [
317           {
318             "property": "id",
319             "value": %d,
320             "operator": "eq"
321           },
322           {
323             "property": "name",
324             "value": "%s",
325             "operator": "eq"
326           }
327       ]}""".formatted(collection1.getId(), collection1.getName());
328     searchParams.setQuery(query);
329     searchBody.setSearchParams(searchParams);
330     var result = given()
331       .spec(requestSpecOfDefaultUser)
332       .body(searchBody)
333       .when()
334       .post(searchURL)
335       .then()
336       .statusCode(200)
337       .extract()
338       .as(ResponseBody.class);
339     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
340     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
341     assertThat(result.getResultSet()).contains(triple1);
342     assertThat(result.getResultSet()).doesNotContain(triple2);
343   }
344 
345   @Test
346   @Order(7)
347   public void unauthorizedCollectionsSearchTest() {
348     SearchBody searchBody = new SearchBody();
349     SearchScope searchScope = new SearchScope();
350     searchScope.setTraversalRules(new TraversalRules[] {});
351     searchBody.setScopes(new SearchScope[] { searchScope });
352     SearchParams searchParams = new SearchParams();
353     searchParams.setQueryType(QueryType.Collection);
354     String query =
355       """
356       {
357         "OR": [
358           {
359             "property": "id",
360             "value": %d,
361             "operator": "ge"
362           },
363           {
364             "property": "id",
365             "value": %d,
366             "operator": "le"
367           }
368       ]}""".formatted(collection1.getId(), collection2.getId());
369     searchParams.setQuery(query);
370     searchBody.setSearchParams(searchParams);
371     var result = given()
372       .spec(requestSpecOfOtherUser)
373       .body(searchBody)
374       .when()
375       .post(searchURL)
376       .then()
377       .statusCode(200)
378       .extract()
379       .as(ResponseBody.class);
380     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
381     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
382     assertThat(result.getResultSet()).doesNotContain(triple1, triple2);
383   }
384 
385   @Test
386   @Order(8)
387   public void authorizedCollectionsSearchTest() {
388     String permissionsURL = "/collections/" + collection1.getId() + "/permissions";
389     PermissionsIO permissions = given()
390       .spec(requestSpecOfDefaultUser)
391       .when()
392       .get(permissionsURL)
393       .then()
394       .statusCode(200)
395       .extract()
396       .as(PermissionsIO.class);
397     String[] reader = { otherUser.getUser().getUsername() };
398     permissions.setReader(reader);
399     given()
400       .spec(requestSpecOfDefaultUser)
401       .body(permissions)
402       .when()
403       .put(permissionsURL)
404       .then()
405       .statusCode(200)
406       .extract()
407       .as(PermissionsIO.class);
408     SearchBody searchBody = new SearchBody();
409     SearchScope searchScope = new SearchScope();
410     searchScope.setTraversalRules(new TraversalRules[] {});
411     searchBody.setScopes(new SearchScope[] { searchScope });
412     SearchParams searchParams = new SearchParams();
413     searchParams.setQueryType(QueryType.Collection);
414     String query =
415       """
416       	{
417         "OR": [
418           {
419             "property": "id",
420             "value": %d,
421             "operator": "ge"
422           },
423           {
424             "property": "id",
425             "value": %d,
426             "operator": "le"
427           }
428       ]}""".formatted(collection1.getId(), collection2.getId());
429     searchParams.setQuery(query);
430     searchBody.setSearchParams(searchParams);
431     var result = given()
432       .spec(requestSpecOfOtherUser)
433       .body(searchBody)
434       .when()
435       .post(searchURL)
436       .then()
437       .statusCode(200)
438       .extract()
439       .as(ResponseBody.class);
440     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
441     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
442     assertThat(result.getResultSet()).contains(triple1);
443     assertThat(result.getResultSet()).doesNotContain(triple2);
444   }
445 
446   @Test
447   @Order(9)
448   public void collectionsSearchTestReaderGroup() {
449     String userGroupURL = "/" + Constants.USERGROUPS;
450     UserGroupIO userGroup = new UserGroupIO();
451     userGroup.setName("userGroup");
452     userGroup.setUsernames(new String[] { otherUser.getUser().getUsername() });
453     UserGroupIO userGroupCreated = given()
454       .spec(requestSpecOfDefaultUser)
455       .body(userGroup)
456       .when()
457       .post(userGroupURL)
458       .then()
459       .statusCode(201)
460       .extract()
461       .as(UserGroupIO.class);
462 
463     String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection2.getId() + "/" + Constants.PERMISSIONS;
464     PermissionsIO permissions = given()
465       .spec(requestSpecOfDefaultUser)
466       .when()
467       .get(permissionsURL)
468       .then()
469       .statusCode(200)
470       .extract()
471       .as(PermissionsIO.class);
472     long[] readerGroupIds = { userGroupCreated.getId() };
473     permissions.setReaderGroupIds(readerGroupIds);
474     given()
475       .spec(requestSpecOfDefaultUser)
476       .body(permissions)
477       .when()
478       .put(permissionsURL)
479       .then()
480       .statusCode(200)
481       .extract()
482       .as(PermissionsIO.class);
483     SearchBody searchBody = new SearchBody();
484     SearchScope searchScope = new SearchScope();
485     searchScope.setTraversalRules(new TraversalRules[] {});
486     searchBody.setScopes(new SearchScope[] { searchScope });
487     SearchParams searchParams = new SearchParams();
488     searchParams.setQueryType(QueryType.Collection);
489     String query =
490       """
491       	{
492         "OR": [
493           {
494             "property": "id",
495             "value": %d,
496             "operator": "ge"
497           },
498           {
499             "property": "id",
500             "value": %d,
501             "operator": "le"
502           }
503       ]}""".formatted(collection1.getId(), collection2.getId());
504     searchParams.setQuery(query);
505     searchBody.setSearchParams(searchParams);
506     var result = given()
507       .spec(requestSpecOfOtherUser)
508       .body(searchBody)
509       .when()
510       .post(searchURL)
511       .then()
512       .statusCode(200)
513       .extract()
514       .as(ResponseBody.class);
515     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
516     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
517     assertThat(result.getResultSet()).contains(triple1);
518     assertThat(result.getResultSet()).contains(triple2);
519   }
520 
521   @Test
522   @Order(10)
523   public void inTest() {
524     String userGroupURL = "/" + Constants.USERGROUPS;
525     UserGroupIO userGroup = new UserGroupIO();
526     userGroup.setName("userGroup");
527     userGroup.setUsernames(new String[] { otherUser.getUser().getUsername() });
528     UserGroupIO userGroupCreated = given()
529       .spec(requestSpecOfDefaultUser)
530       .body(userGroup)
531       .when()
532       .post(userGroupURL)
533       .then()
534       .statusCode(201)
535       .extract()
536       .as(UserGroupIO.class);
537 
538     String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection2.getId() + "/" + Constants.PERMISSIONS;
539     PermissionsIO permissions = given()
540       .spec(requestSpecOfDefaultUser)
541       .when()
542       .get(permissionsURL)
543       .then()
544       .statusCode(200)
545       .extract()
546       .as(PermissionsIO.class);
547     long[] readerGroupIds = { userGroupCreated.getId() };
548     permissions.setReaderGroupIds(readerGroupIds);
549     given()
550       .spec(requestSpecOfDefaultUser)
551       .body(permissions)
552       .when()
553       .put(permissionsURL)
554       .then()
555       .statusCode(200)
556       .extract()
557       .as(PermissionsIO.class);
558     SearchBody searchBody = new SearchBody();
559     SearchScope searchScope = new SearchScope();
560     searchScope.setTraversalRules(new TraversalRules[] {});
561     searchBody.setScopes(new SearchScope[] { searchScope });
562     SearchParams searchParams = new SearchParams();
563     searchParams.setQueryType(QueryType.Collection);
564     String query =
565       """
566       {
567         "property": "id",
568         "value": [%d,%d],
569         "operator": "in"
570       }""".formatted(collection1.getId(), collection2.getId());
571     searchParams.setQuery(query);
572     searchBody.setSearchParams(searchParams);
573     var result = given()
574       .spec(requestSpecOfOtherUser)
575       .body(searchBody)
576       .when()
577       .post(searchURL)
578       .then()
579       .statusCode(200)
580       .extract()
581       .as(ResponseBody.class);
582     ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
583     ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
584     assertThat(result.getResultSet()).contains(triple1);
585     assertThat(result.getResultSet()).contains(triple2);
586   }
587 
588   @Test
589   @Order(11)
590   public void searchCollectionsViaPropertyIRI() {
591     SearchBody searchBody = new SearchBody();
592     SearchScope searchScope = new SearchScope();
593     searchScope.setTraversalRules(new TraversalRules[] {});
594     searchBody.setScopes(new SearchScope[] { searchScope });
595     SearchParams searchParams = new SearchParams();
596     searchParams.setQueryType(QueryType.Collection);
597     String query =
598       "{\"property\": \"propertyIRI\",\"value\": \"" + annotation.getPropertyIRI() + "\",\"operator\": \"eq\"}";
599     searchParams.setQuery(query);
600     searchBody.setSearchParams(searchParams);
601     var result = given()
602       .spec(requestSpecOfDefaultUser)
603       .body(searchBody)
604       .when()
605       .post(searchURL)
606       .then()
607       .statusCode(200)
608       .extract()
609       .as(ResponseBody.class);
610     ResultTriple triple = new ResultTriple(annotatedCollection.getId(), null, null);
611     assertThat(result.getResultSet()).contains(triple);
612   }
613 
614   @Test
615   @Order(12)
616   public void searchCollectionsViaValueIRI() {
617     SearchBody searchBody = new SearchBody();
618     SearchScope searchScope = new SearchScope();
619     searchScope.setTraversalRules(new TraversalRules[] {});
620     searchBody.setScopes(new SearchScope[] { searchScope });
621     SearchParams searchParams = new SearchParams();
622     searchParams.setQueryType(QueryType.Collection);
623     String query =
624       "{\"property\": \"valueIRI\",\"value\": \"" +
625       annotation.getValueIRI().substring(2, 10) +
626       "\",\"operator\": \"contains\"}";
627     searchParams.setQuery(query);
628     searchBody.setSearchParams(searchParams);
629     var result = given()
630       .spec(requestSpecOfDefaultUser)
631       .body(searchBody)
632       .when()
633       .post(searchURL)
634       .then()
635       .statusCode(200)
636       .extract()
637       .as(ResponseBody.class);
638     ResultTriple triple = new ResultTriple(annotatedCollection.getId(), null, null);
639     assertThat(result.getResultSet()).contains(triple);
640   }
641 }