1 package de.dlr.shepard.integrationtests;
2
3 import static io.restassured.RestAssured.given;
4 import static org.assertj.core.api.Assertions.assertThat;
5 import static org.junit.jupiter.api.Assertions.assertEquals;
6
7 import de.dlr.shepard.auth.permission.io.PermissionsIO;
8 import de.dlr.shepard.auth.users.io.UserGroupIO;
9 import de.dlr.shepard.common.neo4j.io.BasicEntityIO;
10 import de.dlr.shepard.common.search.io.QueryType;
11 import de.dlr.shepard.common.search.io.ResponseBody;
12 import de.dlr.shepard.common.search.io.ResultTriple;
13 import de.dlr.shepard.common.search.io.SearchBody;
14 import de.dlr.shepard.common.search.io.SearchParams;
15 import de.dlr.shepard.common.search.io.SearchScope;
16 import de.dlr.shepard.common.util.Constants;
17 import de.dlr.shepard.common.util.TraversalRules;
18 import de.dlr.shepard.context.collection.io.CollectionIO;
19 import de.dlr.shepard.context.collection.io.DataObjectIO;
20 import de.dlr.shepard.context.references.structureddata.io.StructuredDataReferenceIO;
21 import de.dlr.shepard.data.structureddata.entities.StructuredData;
22 import de.dlr.shepard.data.structureddata.entities.StructuredDataPayload;
23 import de.dlr.shepard.data.structureddata.io.StructuredDataContainerIO;
24 import io.quarkus.test.junit.QuarkusIntegrationTest;
25 import io.restassured.builder.RequestSpecBuilder;
26 import io.restassured.http.ContentType;
27 import io.restassured.specification.RequestSpecification;
28 import java.util.Arrays;
29 import java.util.HashSet;
30 import org.junit.jupiter.api.BeforeAll;
31 import org.junit.jupiter.api.MethodOrderer;
32 import org.junit.jupiter.api.Order;
33 import org.junit.jupiter.api.Test;
34 import org.junit.jupiter.api.TestMethodOrder;
35
36 @QuarkusIntegrationTest
37 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
38 public class StructuredDataSearcherIT extends BaseTestCaseIT {
39
40 private static String containerURL;
41 private static CollectionIO collection;
42 private static DataObjectIO rootObject;
43 private static DataObjectIO firstChild;
44 private static DataObjectIO secondChild;
45 private static DataObjectIO secondChildFirstGrandchild;
46 private static DataObjectIO cyclicSuccessor;
47 private static DataObjectIO firstSuccessor;
48 private static StructuredDataContainerIO structuredDataContainer;
49 private static StructuredDataContainerIO structuredDataContainerSuccessor;
50 private static StructuredData structuredData;
51 private static StructuredData structuredData1;
52 private static StructuredData structuredDataSuccessor;
53 private static StructuredDataPayload payload;
54 private static StructuredDataPayload payload1;
55 private static StructuredDataPayload payloadSuccessor;
56 private static String structuredDataOID;
57 private static String structuredDataOID1;
58 private static String structuredDataOIDSuccessor;
59 private static StructuredDataReferenceIO reference;
60 private static StructuredDataReferenceIO reference1;
61 private static StructuredDataReferenceIO referenceSuccessor;
62 private static String searchURL;
63 private static UserWithApiKey user1;
64 private static String jws1;
65 private static RequestSpecification searchRequestSpec1;
66 private static UserWithApiKey user2;
67 private static String jws2;
68 private static RequestSpecification searchRequestSpec2;
69
70 @BeforeAll
71 public static void setUp() {
72 collection = createCollection("SearchTestCollection");
73 rootObject = createDataObject("RootDataObject", collection.getId());
74 firstChild = createDataObjectWithParent("firstChild", collection.getId(), rootObject.getId());
75 secondChild = createDataObjectWithParent("secondChild", collection.getId(), rootObject.getId());
76 secondChildFirstGrandchild = createDataObjectWithParent(
77 "secondChildFirstGrandchild",
78 collection.getId(),
79 secondChild.getId()
80 );
81 long[] firstPredecessorIDs = { firstChild.getId(), secondChild.getId() };
82 firstSuccessor = createDataObjectWithPredecessors("firstSuccessor", collection.getId(), firstPredecessorIDs);
83 structuredDataContainer = createDataContainer("DataContainer");
84 structuredDataContainerSuccessor = createDataContainer("DataContainerSuccessor");
85 cyclicSuccessor = createDataObjectWithPredecessors(
86 "cyclicSuccessor",
87 collection.getId(),
88 new long[] { firstSuccessor.getId() }
89 );
90 long[] newPredecessorIDs = new long[firstSuccessor.getPredecessorIds().length + 1];
91 for (int i = 0; i < firstSuccessor.getPredecessorIds().length; i++) newPredecessorIDs[i] =
92 firstSuccessor.getPredecessorIds()[i];
93 newPredecessorIDs[newPredecessorIDs.length - 1] = cyclicSuccessor.getId();
94 firstSuccessor.setPredecessorIds(newPredecessorIDs);
95 firstSuccessor.setSuccessorIds(null);
96 putDataObject(firstSuccessor.getId(), collection.getId(), firstSuccessor);
97
98 var structuredDataToCreate = new StructuredData();
99 structuredDataToCreate.setName("StructuredData");
100 payload = new StructuredDataPayload(structuredDataToCreate, "{\"number1\":3,\"number2\":456}");
101 structuredData = createStructuredData(structuredDataToCreate, structuredDataContainer.getId(), payload);
102 payload.setStructuredData(structuredData);
103 structuredDataOID = structuredData.getOid();
104 String[] dataOIDs = { structuredDataOID };
105 reference = createStructuredDataReference("reference", dataOIDs, structuredDataContainer, secondChild);
106
107 var structuredDataToCreate1 = new StructuredData();
108 structuredDataToCreate1.setName("StructuredData1");
109 payload1 = new StructuredDataPayload(structuredDataToCreate, "{\"number1\":0,\"number2\":123}");
110 structuredData1 = createStructuredData(structuredDataToCreate1, structuredDataContainer.getId(), payload1);
111 payload1.setStructuredData(structuredData1);
112 structuredDataOID1 = structuredData1.getOid();
113 String[] dataOIDs1 = { structuredDataOID1 };
114 reference1 = createStructuredDataReference("reference1", dataOIDs1, structuredDataContainer, firstChild);
115
116 var structuredDataToCreateSuccessor = new StructuredData();
117 structuredDataToCreateSuccessor.setName("StructuredDataSuccessor");
118 payloadSuccessor = new StructuredDataPayload(structuredDataToCreateSuccessor, "{\"success\":0,\"number2\":123}");
119 structuredDataSuccessor = createStructuredData(
120 structuredDataToCreateSuccessor,
121 structuredDataContainerSuccessor.getId(),
122 payloadSuccessor
123 );
124 payloadSuccessor.setStructuredData(structuredDataSuccessor);
125 structuredDataOIDSuccessor = structuredDataSuccessor.getOid();
126 String[] dataOIDsSuccessor = { structuredDataOIDSuccessor };
127 referenceSuccessor = createStructuredDataReference(
128 "referenceSucessor",
129 dataOIDsSuccessor,
130 structuredDataContainerSuccessor,
131 firstSuccessor
132 );
133
134 searchURL = "/search";
135 user1 = getNewUserWithApiKey("user1" + System.currentTimeMillis());
136 jws1 = user1.getApiKey().getJws();
137 searchRequestSpec1 = new RequestSpecBuilder().setContentType(ContentType.JSON).addHeader("X-API-KEY", jws1).build();
138 user2 = getNewUserWithApiKey("user2" + System.currentTimeMillis());
139 jws2 = user2.getApiKey().getJws();
140 searchRequestSpec2 = new RequestSpecBuilder().setContentType(ContentType.JSON).addHeader("X-API-KEY", jws2).build();
141 }
142
143 @Test
144 @Order(1)
145 public void testFindViaChildren() {
146 SearchBody searchBody = new SearchBody();
147 SearchScope searchScope = new SearchScope();
148 searchScope.setCollectionId(collection.getId());
149 searchScope.setDataObjectId(rootObject.getId());
150 TraversalRules[] traversalRules = { TraversalRules.children };
151 searchScope.setTraversalRules(traversalRules);
152 SearchScope[] scopes = { searchScope };
153 searchBody.setScopes(scopes);
154 SearchParams searchParams = new SearchParams();
155 searchParams.setQueryType(QueryType.StructuredData);
156 String query = "number1: {$gt: 1}";
157 searchParams.setQuery(query);
158 searchBody.setSearchParams(searchParams);
159 var result = given()
160 .spec(requestSpecOfDefaultUser)
161 .body(searchBody)
162 .when()
163 .post(searchURL)
164 .then()
165 .statusCode(200)
166 .extract()
167 .as(ResponseBody.class);
168 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
169 assertThat(result.getResultSet()).containsExactly(triple);
170 assertThat(result.getSearchParams()).isEqualTo(searchParams);
171 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
172 reference.getId()
173 );
174 }
175
176 @Test
177 @Order(2)
178 public void testFindWithoutDataObjectId() {
179 SearchBody searchBody = new SearchBody();
180 SearchScope searchScope = new SearchScope();
181 searchScope.setCollectionId(collection.getId());
182 TraversalRules[] traversalRules = {};
183 searchScope.setTraversalRules(traversalRules);
184 SearchScope[] scopes = { searchScope };
185 searchBody.setScopes(scopes);
186 SearchParams searchParams = new SearchParams();
187 searchParams.setQueryType(QueryType.StructuredData);
188 String query = "number1: {$gt: 1}";
189 searchParams.setQuery(query);
190 searchBody.setSearchParams(searchParams);
191 var result = given()
192 .spec(requestSpecOfDefaultUser)
193 .body(searchBody)
194 .when()
195 .post(searchURL)
196 .then()
197 .statusCode(200)
198 .extract()
199 .as(ResponseBody.class);
200 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
201 assertThat(result.getResultSet()).containsExactly(triple);
202 assertThat(result.getSearchParams()).isEqualTo(searchParams);
203 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
204 reference.getId()
205 );
206 }
207
208 @Test
209 @Order(3)
210 public void testFindViaChildrenUniversalSyntaxAND() {
211 SearchBody searchBody = new SearchBody();
212 SearchScope searchScope = new SearchScope();
213 searchScope.setCollectionId(collection.getId());
214 searchScope.setDataObjectId(rootObject.getId());
215 TraversalRules[] traversalRules = { TraversalRules.children };
216 searchScope.setTraversalRules(traversalRules);
217 SearchScope[] scopes = { searchScope };
218 searchBody.setScopes(scopes);
219 SearchParams searchParams = new SearchParams();
220 searchParams.setQueryType(QueryType.StructuredData);
221 String query =
222 "{\"AND\": [{\"property\": \"number1\", \"value\": 3, \"operator\": \"ge\"},{\"property\": \"number1\",\"value\": 3, \"operator\": \"le\"}]}";
223 searchParams.setQuery(query);
224 searchBody.setSearchParams(searchParams);
225 var result = given()
226 .spec(requestSpecOfDefaultUser)
227 .body(searchBody)
228 .when()
229 .post(searchURL)
230 .then()
231 .statusCode(200)
232 .extract()
233 .as(ResponseBody.class);
234 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
235 assertThat(result.getResultSet()).containsExactly(triple);
236 assertEquals(query, result.getSearchParams().getQuery());
237 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
238 reference.getId()
239 );
240 }
241
242 @Test
243 @Order(4)
244 public void testDoNotFindViaChildren() {
245 SearchBody searchBody = new SearchBody();
246 SearchScope searchScope = new SearchScope();
247 searchScope.setCollectionId(collection.getId());
248 searchScope.setDataObjectId(rootObject.getId());
249 TraversalRules[] traversalRules = { TraversalRules.children };
250 searchScope.setTraversalRules(traversalRules);
251 SearchScope[] scopes = { searchScope };
252 searchBody.setScopes(scopes);
253 SearchParams searchParams = new SearchParams();
254 searchParams.setQueryType(QueryType.StructuredData);
255 String query = "number1: {$lt: 0}";
256 searchParams.setQuery(query);
257 searchBody.setSearchParams(searchParams);
258 var result = given()
259 .spec(requestSpecOfDefaultUser)
260 .body(searchBody)
261 .when()
262 .post(searchURL)
263 .then()
264 .statusCode(200)
265 .extract()
266 .as(ResponseBody.class);
267 assertEquals(0, result.getResultSet().length);
268 assertEquals(0, result.getResults().length);
269 assertThat(result.getSearchParams()).isEqualTo(searchParams);
270 }
271
272 @Test
273 @Order(5)
274 public void testFindViaChildrenUniversalSyntaxOR() {
275 SearchBody searchBody = new SearchBody();
276 SearchScope searchScope = new SearchScope();
277 searchScope.setCollectionId(collection.getId());
278 searchScope.setDataObjectId(rootObject.getId());
279 TraversalRules[] traversalRules = { TraversalRules.children };
280 searchScope.setTraversalRules(traversalRules);
281 SearchScope[] scopes = { searchScope };
282 searchBody.setScopes(scopes);
283 SearchParams searchParams = new SearchParams();
284 searchParams.setQueryType(QueryType.StructuredData);
285 String query =
286 "{\"OR\": [{\"property\": \"number1\", \"value\": 3, \"operator\": \"ge\"}," +
287 "{\"property\": \"number1\",\"value\": 3, \"operator\": \"le\"}]}";
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 assertEquals(2, result.getResultSet().length);
300 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
301 ResultTriple triple1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
302 assertThat(result.getResultSet()).contains(triple);
303 assertThat(result.getResultSet()).contains(triple1);
304 assertEquals(query, result.getSearchParams().getQuery());
305 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
306 reference.getId(),
307 reference1.getId()
308 );
309 }
310
311 @Test
312 @Order(6)
313 public void testFindViaPredecessor() {
314 SearchBody searchBody = new SearchBody();
315 SearchScope searchScope = new SearchScope();
316 searchScope.setCollectionId(collection.getId());
317 searchScope.setDataObjectId(firstSuccessor.getId());
318 TraversalRules[] traversalRules = { TraversalRules.predecessors };
319 searchScope.setTraversalRules(traversalRules);
320 SearchScope[] scopes = { searchScope };
321 searchBody.setScopes(scopes);
322 SearchParams searchParams = new SearchParams();
323 searchParams.setQueryType(QueryType.StructuredData);
324 String query = "number1: {$gt: 1}";
325 searchParams.setQuery(query);
326 searchBody.setSearchParams(searchParams);
327 var result = given()
328 .spec(requestSpecOfDefaultUser)
329 .body(searchBody)
330 .when()
331 .post(searchURL)
332 .then()
333 .statusCode(200)
334 .extract()
335 .as(ResponseBody.class);
336 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
337 assertThat(result.getResultSet()).containsExactly(triple);
338 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
339 reference.getId()
340 );
341 assertThat(result.getSearchParams()).isEqualTo(searchParams);
342 }
343
344 @Test
345 @Order(7)
346 public void testFindViaChildrenUniversalSyntaxNOT() {
347 SearchBody searchBody = new SearchBody();
348 SearchScope searchScope = new SearchScope();
349 searchScope.setCollectionId(collection.getId());
350 searchScope.setDataObjectId(rootObject.getId());
351 TraversalRules[] traversalRules = { TraversalRules.children };
352 searchScope.setTraversalRules(traversalRules);
353 SearchScope[] scopes = { searchScope };
354 searchBody.setScopes(scopes);
355 SearchParams searchParams = new SearchParams();
356 searchParams.setQueryType(QueryType.StructuredData);
357 String query = "{\"NOT\": {\"property\": \"number1\", \"value\": 3, \"operator\": \"eq\"}}";
358 searchParams.setQuery(query);
359 searchBody.setSearchParams(searchParams);
360 var result = given()
361 .spec(requestSpecOfDefaultUser)
362 .body(searchBody)
363 .when()
364 .post(searchURL)
365 .then()
366 .statusCode(200)
367 .extract()
368 .as(ResponseBody.class);
369 assertEquals(1, result.getResultSet().length);
370 ResultTriple triple1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
371 assertThat(result.getResultSet()).contains(triple1);
372 assertEquals(query, result.getSearchParams().getQuery());
373 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).contains(reference1.getId());
374 }
375
376 @Test
377 @Order(8)
378 public void testDoNotFindViaPredecessor() {
379 SearchBody searchBody = new SearchBody();
380 SearchScope searchScope = new SearchScope();
381 searchScope.setCollectionId(collection.getId());
382 searchScope.setDataObjectId(firstSuccessor.getId());
383 TraversalRules[] traversalRules = { TraversalRules.predecessors };
384 searchScope.setTraversalRules(traversalRules);
385 SearchScope[] scopes = { searchScope };
386 searchBody.setScopes(scopes);
387 SearchParams searchParams = new SearchParams();
388 searchParams.setQueryType(QueryType.StructuredData);
389 String query = "number1: {$lt: 0}";
390 searchParams.setQuery(query);
391 searchBody.setSearchParams(searchParams);
392 var result = given()
393 .spec(requestSpecOfDefaultUser)
394 .body(searchBody)
395 .when()
396 .post(searchURL)
397 .then()
398 .statusCode(200)
399 .extract()
400 .as(ResponseBody.class);
401 assertEquals(0, result.getResultSet().length);
402 assertEquals(0, result.getResults().length);
403 assertThat(result.getSearchParams()).isEqualTo(searchParams);
404 }
405
406 @Test
407 @Order(9)
408 public void testFindViaChildrenUniversalSyntaxDeMorgan() {
409 SearchBody searchBody = new SearchBody();
410 SearchScope searchScope = new SearchScope();
411 searchScope.setCollectionId(collection.getId());
412 searchScope.setDataObjectId(rootObject.getId());
413 TraversalRules[] traversalRules = { TraversalRules.children };
414 searchScope.setTraversalRules(traversalRules);
415 SearchScope[] scopes = { searchScope };
416 searchBody.setScopes(scopes);
417 SearchParams searchParams = new SearchParams();
418 searchParams.setQueryType(QueryType.StructuredData);
419 String query =
420 "{\"NOT\": {\"OR\": [{\"property\": \"number1\", \"value\": 4, \"operator\": \"gt\"}," +
421 " {\"property\": \"number1\", \"value\": 1, \"operator\": \"lt\"}]}}";
422 searchParams.setQuery(query);
423 searchBody.setSearchParams(searchParams);
424 var result = given()
425 .spec(requestSpecOfDefaultUser)
426 .body(searchBody)
427 .when()
428 .post(searchURL)
429 .then()
430 .statusCode(200)
431 .extract()
432 .as(ResponseBody.class);
433 assertEquals(1, result.getResultSet().length);
434 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
435 assertThat(result.getResultSet()).contains(triple);
436 assertEquals(query, result.getSearchParams().getQuery());
437 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).contains(reference.getId());
438 }
439
440 @Test
441 @Order(10)
442 public void testFindViaParent() {
443 SearchBody searchBody = new SearchBody();
444 SearchScope searchScope = new SearchScope();
445 searchScope.setCollectionId(collection.getId());
446 searchScope.setDataObjectId(secondChildFirstGrandchild.getId());
447 TraversalRules[] traversalRules = { TraversalRules.parents };
448 searchScope.setTraversalRules(traversalRules);
449 SearchScope[] scopes = { searchScope };
450 searchBody.setScopes(scopes);
451 SearchParams searchParams = new SearchParams();
452 searchParams.setQueryType(QueryType.StructuredData);
453 String query = "number1: {$gt: 1}";
454 searchParams.setQuery(query);
455 searchBody.setSearchParams(searchParams);
456 var result = given()
457 .spec(requestSpecOfDefaultUser)
458 .body(searchBody)
459 .when()
460 .post(searchURL)
461 .then()
462 .statusCode(200)
463 .extract()
464 .as(ResponseBody.class);
465 ResultTriple triple = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
466 assertThat(result.getResultSet()).containsExactly(triple);
467 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
468 reference.getId()
469 );
470 assertThat(result.getSearchParams()).isEqualTo(searchParams);
471 }
472
473 @Test
474 @Order(11)
475 public void testFindViaSuccessor() {
476 SearchBody searchBody = new SearchBody();
477 SearchScope searchScope = new SearchScope();
478 searchScope.setCollectionId(collection.getId());
479 searchScope.setDataObjectId(secondChild.getId());
480 TraversalRules[] traversalRules = { TraversalRules.successors };
481 searchScope.setTraversalRules(traversalRules);
482 SearchScope[] scopes = { searchScope };
483 searchBody.setScopes(scopes);
484 SearchParams searchParams = new SearchParams();
485 searchParams.setQueryType(QueryType.StructuredData);
486 String query = "success: {$eq: 0}";
487 searchParams.setQuery(query);
488 searchBody.setSearchParams(searchParams);
489 var result = given()
490 .spec(requestSpecOfDefaultUser)
491 .body(searchBody)
492 .when()
493 .post(searchURL)
494 .then()
495 .statusCode(200)
496 .extract()
497 .as(ResponseBody.class);
498 ResultTriple triple = new ResultTriple(collection.getId(), firstSuccessor.getId(), referenceSuccessor.getId());
499 assertThat(result.getResultSet()).containsExactly(triple);
500 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
501 referenceSuccessor.getId()
502 );
503 assertThat(result.getSearchParams()).isEqualTo(searchParams);
504 }
505
506 @Test
507 @Order(12)
508 public void testFindMultipleResults() {
509 SearchBody searchBody = new SearchBody();
510 SearchScope searchScope = new SearchScope();
511 searchScope.setCollectionId(collection.getId());
512 searchScope.setDataObjectId(rootObject.getId());
513 TraversalRules[] traversalRules = { TraversalRules.children };
514 searchScope.setTraversalRules(traversalRules);
515 SearchScope[] scopes = { searchScope };
516 searchBody.setScopes(scopes);
517 SearchParams searchParams = new SearchParams();
518 searchParams.setQueryType(QueryType.StructuredData);
519 String query = "number2: {$gt: 0}";
520 searchParams.setQuery(query);
521 searchBody.setSearchParams(searchParams);
522 var result = given()
523 .spec(requestSpecOfDefaultUser)
524 .body(searchBody)
525 .when()
526 .post(searchURL)
527 .then()
528 .statusCode(200)
529 .extract()
530 .as(ResponseBody.class);
531 assertEquals(2, result.getResultSet().length);
532 HashSet<ResultTriple> resultTriples = new HashSet<>();
533 resultTriples.add(result.getResultSet()[0]);
534 resultTriples.add(result.getResultSet()[1]);
535 ResultTriple expectedResult0 = new ResultTriple(collection.getId(), secondChild.getId(), reference.getId());
536 ResultTriple expectedResult1 = new ResultTriple(collection.getId(), firstChild.getId(), reference1.getId());
537 assertThat(resultTriples).containsExactlyInAnyOrder(expectedResult0, expectedResult1);
538 assertThat(Arrays.asList(result.getResults()).stream().map(BasicEntityIO::getId)).containsExactlyInAnyOrder(
539 reference.getId(),
540 reference1.getId()
541 );
542 assertThat(result.getSearchParams()).isEqualTo(searchParams);
543 }
544
545 @Test
546 @Order(13)
547 public void testFindViaPredecessorCycle() {
548 SearchBody searchBody = new SearchBody();
549 SearchScope searchScope = new SearchScope();
550 searchScope.setCollectionId(collection.getId());
551 searchScope.setDataObjectId(cyclicSuccessor.getId());
552 TraversalRules[] traversalRules = { TraversalRules.predecessors };
553 searchScope.setTraversalRules(traversalRules);
554 SearchScope[] scopes = { searchScope };
555 searchBody.setScopes(scopes);
556 SearchParams searchParams = new SearchParams();
557 searchParams.setQueryType(QueryType.StructuredData);
558 String query = "success: {$eq: 0}";
559 searchParams.setQuery(query);
560 searchBody.setSearchParams(searchParams);
561 var result = given()
562 .spec(requestSpecOfDefaultUser)
563 .body(searchBody)
564 .when()
565 .post(searchURL)
566 .then()
567 .statusCode(200)
568 .extract()
569 .as(ResponseBody.class);
570 assertEquals(1, result.getResultSet().length);
571 assertThat(result.getSearchParams()).isEqualTo(searchParams);
572 }
573
574 @Test
575 @Order(14)
576 public void testFindViaPredecessorCycleUnauthorized() {
577 SearchBody searchBody = new SearchBody();
578 SearchScope searchScope = new SearchScope();
579 searchScope.setCollectionId(collection.getId());
580 searchScope.setDataObjectId(cyclicSuccessor.getId());
581 TraversalRules[] traversalRules = { TraversalRules.predecessors };
582 searchScope.setTraversalRules(traversalRules);
583 SearchScope[] scopes = { searchScope };
584 searchBody.setScopes(scopes);
585 SearchParams searchParams = new SearchParams();
586 searchParams.setQueryType(QueryType.StructuredData);
587 String query = "success: {$eq: 0}";
588 searchParams.setQuery(query);
589 searchBody.setSearchParams(searchParams);
590 var result = given()
591 .spec(searchRequestSpec1)
592 .body(searchBody)
593 .when()
594 .post(searchURL)
595 .then()
596 .statusCode(200)
597 .extract()
598 .as(ResponseBody.class);
599 assertEquals(0, result.getResultSet().length);
600 assertEquals(0, result.getResults().length);
601 assertThat(result.getSearchParams()).isEqualTo(searchParams);
602 }
603
604 @Test
605 @Order(15)
606 public void testFindViaPredecessorCyclePermissionsReader() {
607 String permissionsURL = "/collections/" + collection.getId() + "/permissions";
608
609 PermissionsIO permissions = given()
610 .spec(requestSpecOfDefaultUser)
611 .when()
612 .get(permissionsURL)
613 .then()
614 .statusCode(200)
615 .extract()
616 .as(PermissionsIO.class);
617 String[] reader = { user1.getUser().getUsername() };
618 permissions.setReader(reader);
619 given()
620 .spec(requestSpecOfDefaultUser)
621 .body(permissions)
622 .when()
623 .put(permissionsURL)
624 .then()
625 .statusCode(200)
626 .extract()
627 .as(PermissionsIO.class);
628 SearchBody searchBody = new SearchBody();
629 SearchScope searchScope = new SearchScope();
630 searchScope.setCollectionId(collection.getId());
631 searchScope.setDataObjectId(cyclicSuccessor.getId());
632 TraversalRules[] traversalRules = { TraversalRules.predecessors };
633 searchScope.setTraversalRules(traversalRules);
634 SearchScope[] scopes = { searchScope };
635 searchBody.setScopes(scopes);
636 SearchParams searchParams = new SearchParams();
637 searchParams.setQueryType(QueryType.StructuredData);
638 String query = "success: {$eq: 0}";
639 searchParams.setQuery(query);
640 searchBody.setSearchParams(searchParams);
641 var result = given()
642 .spec(searchRequestSpec1)
643 .body(searchBody)
644 .when()
645 .post(searchURL)
646 .then()
647 .statusCode(200)
648 .extract()
649 .as(ResponseBody.class);
650 assertEquals(1, result.getResultSet().length);
651 assertThat(result.getSearchParams()).isEqualTo(searchParams);
652 }
653
654 @Test
655 @Order(16)
656 public void testFindViaPredecessorCycleReaderGroup() {
657 String userGroupURL = "/" + Constants.USERGROUPS;
658 UserGroupIO userGroup = new UserGroupIO();
659 userGroup.setName("userGroup");
660 userGroup.setUsernames(new String[] { user2.getUser().getUsername() });
661 UserGroupIO userGroupCreated = given()
662 .spec(requestSpecOfDefaultUser)
663 .body(userGroup)
664 .when()
665 .post(userGroupURL)
666 .then()
667 .statusCode(201)
668 .extract()
669 .as(UserGroupIO.class);
670
671 String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection.getId() + "/" + Constants.PERMISSIONS;
672 PermissionsIO permissions = given()
673 .spec(requestSpecOfDefaultUser)
674 .when()
675 .get(permissionsURL)
676 .then()
677 .statusCode(200)
678 .extract()
679 .as(PermissionsIO.class);
680 long[] readerGroupsIds = { userGroupCreated.getId() };
681 permissions.setReaderGroupIds(readerGroupsIds);
682 given()
683 .spec(requestSpecOfDefaultUser)
684 .body(permissions)
685 .when()
686 .put(permissionsURL)
687 .then()
688 .statusCode(200)
689 .extract()
690 .as(PermissionsIO.class);
691 SearchBody searchBody = new SearchBody();
692 SearchScope searchScope = new SearchScope();
693 searchScope.setCollectionId(collection.getId());
694 searchScope.setDataObjectId(cyclicSuccessor.getId());
695 TraversalRules[] traversalRules = { TraversalRules.predecessors };
696 searchScope.setTraversalRules(traversalRules);
697 SearchScope[] scopes = { searchScope };
698 searchBody.setScopes(scopes);
699 SearchParams searchParams = new SearchParams();
700 searchParams.setQueryType(QueryType.StructuredData);
701 String query = "success: {$eq: 0}";
702 searchParams.setQuery(query);
703 searchBody.setSearchParams(searchParams);
704 var result = given()
705 .spec(searchRequestSpec2)
706 .body(searchBody)
707 .when()
708 .post(searchURL)
709 .then()
710 .statusCode(200)
711 .extract()
712 .as(ResponseBody.class);
713 assertEquals(1, result.getResultSet().length);
714 assertThat(result.getSearchParams()).isEqualTo(searchParams);
715 }
716
717 @Test
718 @Order(17)
719 public void testDoNotFindViaDeletedNode() {
720 deleteDataObject(secondChild);
721 SearchBody searchBody = new SearchBody();
722 SearchScope searchScope = new SearchScope();
723 searchScope.setCollectionId(collection.getId());
724 searchScope.setDataObjectId(rootObject.getId());
725 TraversalRules[] traversalRules = { TraversalRules.children };
726 searchScope.setTraversalRules(traversalRules);
727 SearchScope[] scopes = { searchScope };
728 searchBody.setScopes(scopes);
729 SearchParams searchParams = new SearchParams();
730 searchParams.setQueryType(QueryType.StructuredData);
731 String query = "number1: {$gt: 1}";
732 searchParams.setQuery(query);
733 searchBody.setSearchParams(searchParams);
734 var result = given()
735 .spec(requestSpecOfDefaultUser)
736 .body(searchBody)
737 .when()
738 .post(searchURL)
739 .then()
740 .statusCode(200)
741 .extract()
742 .as(ResponseBody.class);
743 assertEquals(0, result.getResultSet().length);
744 assertThat(result.getSearchParams()).isEqualTo(searchParams);
745 }
746
747 private static DataObjectIO createDataObjectWithParent(String name, long collectionId, long parentID) {
748 var dataObjectsURL = "/%s/%d/%s/".formatted(Constants.COLLECTIONS, collectionId, Constants.DATA_OBJECTS);
749 DataObjectIO dataObjectIO = new DataObjectIO();
750 dataObjectIO.setName(name);
751 dataObjectIO.setParentId(parentID);
752 var dataObject = given()
753 .spec(requestSpecOfDefaultUser)
754 .body(dataObjectIO)
755 .when()
756 .post(dataObjectsURL)
757 .then()
758 .statusCode(201)
759 .extract()
760 .as(DataObjectIO.class);
761 return dataObject;
762 }
763
764 private static DataObjectIO createDataObjectWithPredecessors(String name, long collectionId, long[] predecessorsIDs) {
765 var dataObjectsURL = "/%s/%d/%s/".formatted(Constants.COLLECTIONS, collectionId, Constants.DATA_OBJECTS);
766 DataObjectIO dataObjectIO = new DataObjectIO();
767 dataObjectIO.setName(name);
768 dataObjectIO.setPredecessorIds(predecessorsIDs);
769 var dataObject = given()
770 .spec(requestSpecOfDefaultUser)
771 .body(dataObjectIO)
772 .when()
773 .post(dataObjectsURL)
774 .then()
775 .statusCode(201)
776 .extract()
777 .as(DataObjectIO.class);
778 return dataObject;
779 }
780
781 private static StructuredDataContainerIO createDataContainer(String name) {
782 containerURL = "/" + Constants.STRUCTURED_DATA_CONTAINERS;
783 StructuredDataContainerIO containerToCreate = new StructuredDataContainerIO();
784 containerToCreate.setName(name);
785 return given()
786 .spec(requestSpecOfDefaultUser)
787 .body(containerToCreate)
788 .when()
789 .post(containerURL)
790 .then()
791 .statusCode(201)
792 .extract()
793 .as(StructuredDataContainerIO.class);
794 }
795
796 private static StructuredData createStructuredData(
797 StructuredData structuredDataToCreate,
798 long containerID,
799 StructuredDataPayload payload
800 ) {
801 containerURL = "/" + Constants.STRUCTURED_DATA_CONTAINERS;
802 return given()
803 .spec(requestSpecOfDefaultUser)
804 .body(payload)
805 .when()
806 .post("%s/%d/%s".formatted(containerURL, containerID, Constants.PAYLOAD))
807 .then()
808 .statusCode(201)
809 .extract()
810 .as(StructuredData.class);
811 }
812
813 private static StructuredDataReferenceIO createStructuredDataReference(
814 String name,
815 String[] structuredDataOIDs,
816 StructuredDataContainerIO container,
817 DataObjectIO dataObject
818 ) {
819 StructuredDataReferenceIO toCreate = new StructuredDataReferenceIO();
820 toCreate.setName(name);
821 toCreate.setStructuredDataOids(structuredDataOIDs);
822 toCreate.setStructuredDataContainerId(container.getId());
823 String referencesURL =
824 "/%s/%d/%s/%d/%s".formatted(
825 Constants.COLLECTIONS,
826 collection.getId(),
827 Constants.DATA_OBJECTS,
828 dataObject.getId(),
829 Constants.STRUCTURED_DATA_REFERENCES
830 );
831 return given()
832 .spec(requestSpecOfDefaultUser)
833 .body(toCreate)
834 .when()
835 .post(referencesURL)
836 .then()
837 .statusCode(201)
838 .extract()
839 .as(StructuredDataReferenceIO.class);
840 }
841
842 private static void deleteDataObject(DataObjectIO dataObject) {
843 String dataObjectsURL = "/%s/%d/%s".formatted(Constants.COLLECTIONS, collection.getId(), Constants.DATA_OBJECTS);
844 given()
845 .spec(requestSpecOfDefaultUser)
846 .when()
847 .delete(dataObjectsURL + "/" + dataObject.getId())
848 .then()
849 .statusCode(204);
850 }
851
852 private static void putDataObject(Long dataObjectToChangeID, Long collectionID, DataObjectIO changedDataObject) {
853 String putURL = "/%s/%d/%s".formatted(Constants.COLLECTIONS, collection.getId(), Constants.DATA_OBJECTS);
854 putURL = putURL + "/" + dataObjectToChangeID;
855 given().spec(requestSpecOfDefaultUser).body(changedDataObject).when().put(putURL).then().statusCode(200);
856 }
857 }