View Javadoc
1   package de.dlr.shepard.context.collection.daos;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertTrue;
5   import static org.mockito.Mockito.doReturn;
6   import static org.mockito.Mockito.spy;
7   import static org.mockito.Mockito.verify;
8   import static org.mockito.Mockito.when;
9   
10  import de.dlr.shepard.BaseTestCase;
11  import de.dlr.shepard.auth.users.entities.User;
12  import de.dlr.shepard.common.util.CypherQueryHelper;
13  import de.dlr.shepard.common.util.QueryParamHelper;
14  import de.dlr.shepard.context.collection.endpoints.DataObjectAttributes;
15  import de.dlr.shepard.context.collection.entities.Collection;
16  import de.dlr.shepard.context.collection.entities.DataObject;
17  import java.util.Collections;
18  import java.util.Date;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.UUID;
23  import org.junit.jupiter.api.Test;
24  import org.mockito.InjectMocks;
25  import org.mockito.Mock;
26  import org.neo4j.ogm.session.Session;
27  
28  public class DataObjectDAOTest extends BaseTestCase {
29  
30    @Mock
31    private Session session;
32  
33    @InjectMocks
34    private DataObjectDAO dao;
35  
36    @Test
37    public void getEntityTypeTest() {
38      var type = dao.getEntityType();
39      assertEquals(DataObject.class, type);
40    }
41  
42    @Test
43    public void findAllTest() {
44      var c1 = new Collection(100L);
45      var c2 = new Collection(200L);
46  
47      var d1 = new DataObject(1L);
48      var d2 = new DataObject(2L);
49      var d3 = new DataObject(3L);
50      d1.setCollection(c1);
51      d3.setCollection(c2);
52      d1.setChildren(List.of(d2, d3));
53      Map<String, Object> paramsMap = new HashMap<>();
54      paramsMap.put("name", null);
55  
56      String query =
57        """
58        MATCH (c:Collection)-[hdo:has_dataobject]->\
59        (d:DataObject { deleted: FALSE }) WHERE ID(c)=100 WITH d \
60        MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
61        RETURN d, nodes(path), relationships(path)""";
62      when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
63  
64      var params = new QueryParamHelper();
65      var actual = dao.findByCollectionByNeo4jIds(100L, params);
66      verify(session).query(DataObject.class, query, paramsMap);
67      assertEquals(List.of(d1), actual);
68    }
69  
70    @Test
71    public void findAllByShepardIdsTest() {
72      var c1 = new Collection(100L);
73      c1.setShepardId(1001L);
74      var c2 = new Collection(200L);
75      c2.setShepardId(2001L);
76  
77      var d1 = new DataObject(1L);
78      d1.setShepardId(11L);
79      var d2 = new DataObject(2L);
80      d2.setShepardId(21L);
81      var d3 = new DataObject(3L);
82      d3.setShepardId(31L);
83      d1.setCollection(c1);
84      d3.setCollection(c2);
85      d1.setChildren(List.of(d2, d3));
86      Map<String, Object> paramsMap = new HashMap<>();
87      paramsMap.put("name", null);
88  
89      String query =
90        "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
91        CypherQueryHelper.getVersionHeadPart("v") +
92        " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
93      when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
94  
95      var params = new QueryParamHelper();
96      var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
97      verify(session).query(DataObject.class, query, paramsMap);
98      assertEquals(List.of(d1), actual);
99    }
100 
101   @Test
102   public void findAllByShepardIdsWithVersionUIDTest() {
103     var c1 = new Collection(100L);
104     c1.setShepardId(1001L);
105     var c2 = new Collection(200L);
106     c2.setShepardId(2001L);
107 
108     var d1 = new DataObject(1L);
109     d1.setShepardId(11L);
110     var d2 = new DataObject(2L);
111     d2.setShepardId(21L);
112     var d3 = new DataObject(3L);
113     d3.setShepardId(31L);
114     d1.setCollection(c1);
115     d3.setCollection(c2);
116     d1.setChildren(List.of(d2, d3));
117     UUID versionUID = new UUID(0L, 1L);
118     Map<String, Object> paramsMap = new HashMap<>();
119     paramsMap.put("name", null);
120 
121     String query =
122       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND (v.uid = '00000000-0000-0000-0000-000000000001') WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
123     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
124 
125     var params = new QueryParamHelper();
126     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params, versionUID);
127     verify(session).query(DataObject.class, query, paramsMap);
128     assertEquals(List.of(d1), actual);
129   }
130 
131   @Test
132   public void findAllTestOrderByNameDesc() {
133     var c1 = new Collection(100L);
134     var c2 = new Collection(200L);
135 
136     var d1 = new DataObject(1L);
137     var d2 = new DataObject(2L);
138     var d3 = new DataObject(3L);
139     d1.setCollection(c1);
140     d3.setCollection(c2);
141     d1.setChildren(List.of(d2, d3));
142     Map<String, Object> paramsMap = new HashMap<>();
143     paramsMap.put("name", null);
144 
145     String query =
146       """
147       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
148       WHERE ID(c)=100 WITH d ORDER BY toLower(d.name) DESC \
149       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
150       RETURN d, nodes(path), relationships(path)""";
151     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
152 
153     var params = new QueryParamHelper();
154     var dataObjectAttribute = DataObjectAttributes.name;
155     params = params.withOrderByAttribute(dataObjectAttribute, true);
156     var actual = dao.findByCollectionByNeo4jIds(100L, params);
157     verify(session).query(DataObject.class, query, paramsMap);
158     assertEquals(List.of(d1), actual);
159   }
160 
161   @Test
162   public void findAllByShepardIdsTestOrderByNameDesc() {
163     var c1 = new Collection(100L);
164     c1.setShepardId(1001L);
165     var c2 = new Collection(200L);
166     c2.setShepardId(2001L);
167 
168     var d1 = new DataObject(1L);
169     d1.setShepardId(11L);
170     var d2 = new DataObject(2L);
171     d2.setShepardId(21L);
172     var d3 = new DataObject(3L);
173     d3.setShepardId(31L);
174     d1.setCollection(c1);
175     d3.setCollection(c2);
176     d1.setChildren(List.of(d2, d3));
177     Map<String, Object> paramsMap = new HashMap<>();
178     paramsMap.put("name", null);
179 
180     String query =
181       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
182       CypherQueryHelper.getVersionHeadPart("v") +
183       " WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
184     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
185 
186     var params = new QueryParamHelper();
187     var dataObjectAttribute = DataObjectAttributes.name;
188     params = params.withOrderByAttribute(dataObjectAttribute, true);
189     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
190     verify(session).query(DataObject.class, query, paramsMap);
191     assertEquals(List.of(d1), actual);
192   }
193 
194   @Test
195   public void findByPageTest() {
196     var c1 = new Collection(100L);
197     var c2 = new Collection(200L);
198 
199     var d1 = new DataObject(1L);
200     var d2 = new DataObject(2L);
201     var d3 = new DataObject(3L);
202     d1.setCollection(c1);
203     d3.setCollection(c2);
204     d1.setChildren(List.of(d2, d3));
205     Map<String, Object> paramsMap = new HashMap<>();
206     paramsMap.put("name", null);
207     paramsMap.put("offset", 300);
208     paramsMap.put("size", 100);
209 
210     String query =
211       """
212       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
213       WHERE ID(c)=100 WITH d SKIP $offset LIMIT $size \
214       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
215       RETURN d, nodes(path), relationships(path)""";
216     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
217 
218     var params = new QueryParamHelper().withPageAndSize(3, 100);
219     var actual = dao.findByCollectionByNeo4jIds(100L, params);
220     verify(session).query(DataObject.class, query, paramsMap);
221     assertEquals(List.of(d1), actual);
222   }
223 
224   @Test
225   public void findByPageByShepardIdsTest() {
226     var c1 = new Collection(100L);
227     c1.setShepardId(1001L);
228     var c2 = new Collection(200L);
229     c2.setShepardId(2001L);
230 
231     var d1 = new DataObject(1L);
232     d1.setShepardId(11L);
233     var d2 = new DataObject(2L);
234     d2.setShepardId(21L);
235     var d3 = new DataObject(3L);
236     d3.setShepardId(31L);
237     d1.setCollection(c1);
238     d3.setCollection(c2);
239     d1.setChildren(List.of(d2, d3));
240     Map<String, Object> paramsMap = new HashMap<>();
241     paramsMap.put("name", null);
242     paramsMap.put("offset", 300);
243     paramsMap.put("size", 100);
244 
245     String query =
246       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
247       CypherQueryHelper.getVersionHeadPart("v") +
248       " WITH d SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
249     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
250 
251     var params = new QueryParamHelper().withPageAndSize(3, 100);
252     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
253     verify(session).query(DataObject.class, query, paramsMap);
254     assertEquals(List.of(d1), actual);
255   }
256 
257   @Test
258   public void findByPageTestOrderByNameDesc() {
259     var c1 = new Collection(100L);
260     var c2 = new Collection(200L);
261 
262     var d1 = new DataObject(1L);
263     var d2 = new DataObject(2L);
264     var d3 = new DataObject(3L);
265     d1.setCollection(c1);
266     d3.setCollection(c2);
267     d1.setChildren(List.of(d2, d3));
268     Map<String, Object> paramsMap = new HashMap<>();
269     paramsMap.put("name", null);
270     paramsMap.put("offset", 300);
271     paramsMap.put("size", 100);
272 
273     String query =
274       """
275       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
276       WHERE ID(c)=100 WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size \
277       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
278       RETURN d, nodes(path), relationships(path)""";
279     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
280 
281     var params = new QueryParamHelper().withPageAndSize(3, 100);
282     var dataObjectAttribute = DataObjectAttributes.name;
283     params = params.withOrderByAttribute(dataObjectAttribute, true);
284     var actual = dao.findByCollectionByNeo4jIds(100L, params);
285     verify(session).query(DataObject.class, query, paramsMap);
286     assertEquals(List.of(d1), actual);
287   }
288 
289   @Test
290   public void findByPageByShepardIdsTestOrderByNameDesc() {
291     var c1 = new Collection(100L);
292     c1.setShepardId(1001L);
293     var c2 = new Collection(200L);
294     c2.setShepardId(2001L);
295 
296     var d1 = new DataObject(1L);
297     d1.setShepardId(11L);
298     var d2 = new DataObject(2L);
299     d2.setShepardId(21L);
300     var d3 = new DataObject(3L);
301     d3.setShepardId(31L);
302     d1.setCollection(c1);
303     d3.setCollection(c2);
304     d1.setChildren(List.of(d2, d3));
305     Map<String, Object> paramsMap = new HashMap<>();
306     paramsMap.put("name", null);
307     paramsMap.put("offset", 300);
308     paramsMap.put("size", 100);
309 
310     String query =
311       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
312       CypherQueryHelper.getVersionHeadPart("v") +
313       " WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
314     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
315 
316     var params = new QueryParamHelper().withPageAndSize(3, 100);
317     var dataObjectAttribute = DataObjectAttributes.name;
318     params = params.withOrderByAttribute(dataObjectAttribute, true);
319     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
320     verify(session).query(DataObject.class, query, paramsMap);
321     assertEquals(List.of(d1), actual);
322   }
323 
324   @Test
325   public void findByNameTest() {
326     var c1 = new Collection(100L);
327     var d1 = new DataObject(1L);
328     var d2 = new DataObject(2L);
329     d1.setCollection(c1);
330     d1.setName("Yes");
331     d2.setCollection(c1);
332     d2.setName("No");
333     Map<String, Object> paramsMap = Map.of("name", "Yes");
334 
335     String query =
336       """
337       MATCH (c:Collection)-[hdo:has_dataobject]->\
338       (d:DataObject { name : $name, deleted: FALSE }) WHERE ID(c)=100 WITH d \
339       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
340       RETURN d, nodes(path), relationships(path)""";
341     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
342 
343     var params = new QueryParamHelper().withName("Yes");
344     var actual = dao.findByCollectionByNeo4jIds(100L, params);
345     verify(session).query(DataObject.class, query, paramsMap);
346     assertEquals(List.of(d1), actual);
347   }
348 
349   @Test
350   public void findByNameByShepardIdsTest() {
351     var c1 = new Collection(100L);
352     c1.setShepardId(1001L);
353     var d1 = new DataObject(1L);
354     d1.setShepardId(11L);
355     var d2 = new DataObject(2L);
356     d2.setShepardId(21L);
357     d1.setCollection(c1);
358     d1.setName("Yes");
359     d2.setCollection(c1);
360     d2.setName("No");
361     Map<String, Object> paramsMap = Map.of("name", "Yes");
362 
363     String query =
364       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
365       CypherQueryHelper.getVersionHeadPart("v") +
366       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
367     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
368 
369     var params = new QueryParamHelper().withName("Yes");
370     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
371     verify(session).query(DataObject.class, query, paramsMap);
372     assertEquals(List.of(d1), actual);
373   }
374 
375   @Test
376   public void findByNameTestOrderByNameDesc() {
377     var c1 = new Collection(100L);
378     var d1 = new DataObject(1L);
379     var d2 = new DataObject(2L);
380     d1.setCollection(c1);
381     d1.setName("Yes");
382     d2.setCollection(c1);
383     d2.setName("No");
384     Map<String, Object> paramsMap = Map.of("name", "Yes");
385 
386     String query =
387       """
388       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) \
389       WHERE ID(c)=100 WITH d ORDER BY toLower(d.name) DESC \
390       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
391       RETURN d, nodes(path), relationships(path)""";
392     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
393 
394     var params = new QueryParamHelper().withName("Yes");
395     var dataObjectAttribute = DataObjectAttributes.name;
396     params = params.withOrderByAttribute(dataObjectAttribute, true);
397     var actual = dao.findByCollectionByNeo4jIds(100L, params);
398     verify(session).query(DataObject.class, query, paramsMap);
399     assertEquals(List.of(d1), actual);
400   }
401 
402   @Test
403   public void findByNameByShepardIdsTestOrderByNameDesc() {
404     var c1 = new Collection(100L);
405     c1.setShepardId(1001L);
406     var d1 = new DataObject(1L);
407     d1.setShepardId(11L);
408     var d2 = new DataObject(2L);
409     d2.setShepardId(21L);
410     d1.setCollection(c1);
411     d1.setName("Yes");
412     d2.setCollection(c1);
413     d2.setName("No");
414     Map<String, Object> paramsMap = Map.of("name", "Yes");
415 
416     String query =
417       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
418       CypherQueryHelper.getVersionHeadPart("v") +
419       " WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
420     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
421 
422     var params = new QueryParamHelper().withName("Yes");
423     var dataObjectAttribute = DataObjectAttributes.name;
424     params = params.withOrderByAttribute(dataObjectAttribute, true);
425     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
426     verify(session).query(DataObject.class, query, paramsMap);
427     assertEquals(List.of(d1), actual);
428   }
429 
430   @Test
431   public void findByNameAndPageTest() {
432     var c1 = new Collection(100L);
433     var d1 = new DataObject(1L);
434     var d2 = new DataObject(2L);
435     d1.setCollection(c1);
436     d1.setName("Yes");
437     d2.setCollection(c1);
438     d2.setName("No");
439     Map<String, Object> paramsMap = new HashMap<>();
440     paramsMap.put("name", "Yes");
441     paramsMap.put("offset", 300);
442     paramsMap.put("size", 100);
443 
444     String query =
445       """
446       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) \
447       WHERE ID(c)=100 WITH d SKIP $offset LIMIT $size \
448       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
449       RETURN d, nodes(path), relationships(path)""";
450     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
451 
452     var params = new QueryParamHelper().withPageAndSize(3, 100).withName("Yes");
453     var actual = dao.findByCollectionByNeo4jIds(100L, params);
454     verify(session).query(DataObject.class, query, paramsMap);
455     assertEquals(List.of(d1), actual);
456   }
457 
458   @Test
459   public void findByNameAndPageByShepardIdsTest() {
460     var c1 = new Collection(100L);
461     c1.setShepardId(1001L);
462     var d1 = new DataObject(1L);
463     d1.setShepardId(11L);
464     var d2 = new DataObject(2L);
465     d2.setShepardId(21L);
466     d1.setCollection(c1);
467     d1.setName("Yes");
468     d2.setCollection(c1);
469     d2.setName("No");
470     Map<String, Object> paramsMap = new HashMap<>();
471     paramsMap.put("name", "Yes");
472     paramsMap.put("offset", 300);
473     paramsMap.put("size", 100);
474 
475     String query =
476       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
477       CypherQueryHelper.getVersionHeadPart("v") +
478       " WITH d SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
479     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
480 
481     var params = new QueryParamHelper().withPageAndSize(3, 100).withName("Yes");
482     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
483     verify(session).query(DataObject.class, query, paramsMap);
484     assertEquals(List.of(d1), actual);
485   }
486 
487   @Test
488   public void findByNameAndPageTestOrderByNameDesc() {
489     var c1 = new Collection(100L);
490     var d1 = new DataObject(1L);
491     var d2 = new DataObject(2L);
492     d1.setCollection(c1);
493     d1.setName("Yes");
494     d2.setCollection(c1);
495     d2.setName("No");
496     Map<String, Object> paramsMap = new HashMap<>();
497     paramsMap.put("name", "Yes");
498     paramsMap.put("offset", 300);
499     paramsMap.put("size", 100);
500 
501     String query =
502       """
503       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) \
504       WHERE ID(c)=100 WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size \
505       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
506       RETURN d, nodes(path), relationships(path)""";
507     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
508 
509     var params = new QueryParamHelper().withPageAndSize(3, 100).withName("Yes");
510     var dataObjectAttribute = DataObjectAttributes.name;
511     params = params.withOrderByAttribute(dataObjectAttribute, true);
512     var actual = dao.findByCollectionByNeo4jIds(100L, params);
513     verify(session).query(DataObject.class, query, paramsMap);
514     assertEquals(List.of(d1), actual);
515   }
516 
517   @Test
518   public void findByNameAndPageByShepardIdsTestOrderByNameDesc() {
519     var c1 = new Collection(100L);
520     c1.setShepardId(1001L);
521     var d1 = new DataObject(1L);
522     d1.setShepardId(11L);
523     var d2 = new DataObject(2L);
524     d2.setShepardId(21L);
525     d1.setCollection(c1);
526     d1.setName("Yes");
527     d2.setCollection(c1);
528     d2.setName("No");
529     Map<String, Object> paramsMap = new HashMap<>();
530     paramsMap.put("name", "Yes");
531     paramsMap.put("offset", 300);
532     paramsMap.put("size", 100);
533 
534     String query =
535       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
536       CypherQueryHelper.getVersionHeadPart("v") +
537       " WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
538     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
539 
540     var params = new QueryParamHelper().withPageAndSize(3, 100).withName("Yes");
541     var dataObjectAttribute = DataObjectAttributes.name;
542     params = params.withOrderByAttribute(dataObjectAttribute, true);
543     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
544     verify(session).query(DataObject.class, query, paramsMap);
545     assertEquals(List.of(d1), actual);
546   }
547 
548   @Test
549   public void findByParentTest() {
550     var c1 = new Collection(100L);
551     var c2 = new Collection(200L);
552     var d1 = new DataObject(1L);
553     var d2 = new DataObject(2L);
554     var d3 = new DataObject(3L);
555     var d4 = new DataObject(4L);
556     var d5 = new DataObject(5L);
557     d1.setCollection(c1);
558     d2.setCollection(c1);
559     d2.setParent(d1);
560     d3.setCollection(c2);
561     d3.setParent(d1);
562     d4.setParent(d1);
563     d5.setCollection(c1);
564     d5.setParent(d2);
565     Map<String, Object> paramsMap = new HashMap<>();
566     paramsMap.put("name", null);
567 
568     String query =
569       """
570       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
571       <-[:has_child]-(parent:DataObject {deleted: FALSE}) WHERE ID(c)=100 AND ID(parent)=1 WITH d \
572       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
573       RETURN d, nodes(path), relationships(path)""";
574     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
575 
576     var params = new QueryParamHelper().withParentId(1L);
577     var actual = dao.findByCollectionByNeo4jIds(100L, params);
578     verify(session).query(DataObject.class, query, paramsMap);
579     verify(session).query(DataObject.class, query, paramsMap);
580     assertEquals(List.of(d2), actual);
581   }
582 
583   @Test
584   public void findByParentByShepardIdsTest() {
585     var c1 = new Collection(100L);
586     c1.setShepardId(1001L);
587     var c2 = new Collection(200L);
588     c2.setShepardId(2001L);
589     var d1 = new DataObject(1L);
590     d1.setShepardId(11L);
591     var d2 = new DataObject(2L);
592     d2.setShepardId(21L);
593     var d3 = new DataObject(3L);
594     d3.setShepardId(31L);
595     var d4 = new DataObject(4L);
596     d4.setShepardId(41L);
597     var d5 = new DataObject(5L);
598     d5.setShepardId(51L);
599     d1.setCollection(c1);
600     d2.setCollection(c1);
601     d2.setParent(d1);
602     d3.setCollection(c2);
603     d3.setParent(d1);
604     d4.setParent(d1);
605     d5.setCollection(c1);
606     d5.setParent(d2);
607     Map<String, Object> paramsMap = new HashMap<>();
608     paramsMap.put("name", null);
609 
610     String query =
611       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
612       CypherQueryHelper.getVersionHeadPart("v") +
613       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
614     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
615 
616     var params = new QueryParamHelper().withParentId(d1.getShepardId());
617     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
618     verify(session).query(DataObject.class, query, paramsMap);
619     verify(session).query(DataObject.class, query, paramsMap);
620     assertEquals(List.of(d2), actual);
621   }
622 
623   @Test
624   public void findByParentDeletedTest() {
625     var c1 = new Collection(100L);
626     var d1 = new DataObject(1L);
627     var d2 = new DataObject(2L);
628     d1.setCollection(c1);
629     d1.setDeleted(true);
630     d2.setCollection(c1);
631     d2.setParent(d1);
632     Map<String, Object> paramsMap = new HashMap<>();
633     paramsMap.put("name", null);
634 
635     String query =
636       """
637       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
638       <-[:has_child]-(parent:DataObject {deleted: FALSE}) WHERE ID(c)=100 AND ID(parent)=1 WITH d \
639       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
640       RETURN d, nodes(path), relationships(path)""";
641     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
642 
643     var params = new QueryParamHelper().withParentId(1L);
644     var actual = dao.findByCollectionByNeo4jIds(100L, params);
645     verify(session).query(DataObject.class, query, paramsMap);
646     verify(session).query(DataObject.class, query, paramsMap);
647     assertEquals(Collections.EMPTY_LIST, actual);
648   }
649 
650   @Test
651   public void findByParentDeletedByShepardIdTest() {
652     var c1 = new Collection(100L);
653     c1.setShepardId(1001L);
654     var d1 = new DataObject(1L);
655     d1.setShepardId(11L);
656     var d2 = new DataObject(2L);
657     d2.setShepardId(21L);
658     d1.setCollection(c1);
659     d1.setDeleted(true);
660     d2.setCollection(c1);
661     d2.setParent(d1);
662     Map<String, Object> paramsMap = new HashMap<>();
663     paramsMap.put("name", null);
664 
665     String query =
666       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
667       CypherQueryHelper.getVersionHeadPart("v") +
668       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
669     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
670 
671     var params = new QueryParamHelper().withParentId(d1.getShepardId());
672     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
673     verify(session).query(DataObject.class, query, paramsMap);
674     verify(session).query(DataObject.class, query, paramsMap);
675     assertEquals(Collections.EMPTY_LIST, actual);
676   }
677 
678   @Test
679   public void findByParentTestOrderByNameDesc() {
680     var c1 = new Collection(100L);
681     var c2 = new Collection(200L);
682     var d1 = new DataObject(1L);
683     var d2 = new DataObject(2L);
684     var d3 = new DataObject(3L);
685     var d4 = new DataObject(4L);
686     var d5 = new DataObject(5L);
687     d1.setCollection(c1);
688     d2.setCollection(c1);
689     d2.setParent(d1);
690     d3.setCollection(c2);
691     d3.setParent(d1);
692     d4.setParent(d1);
693     d5.setCollection(c1);
694     d5.setParent(d2);
695     Map<String, Object> paramsMap = new HashMap<>();
696     paramsMap.put("name", null);
697 
698     String query =
699       """
700       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
701       <-[:has_child]-(parent:DataObject {deleted: FALSE}) \
702       WHERE ID(c)=100 AND ID(parent)=1 WITH d ORDER BY toLower(d.name) DESC \
703       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
704       RETURN d, nodes(path), relationships(path)""";
705     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
706 
707     var params = new QueryParamHelper().withParentId(1L);
708     var dataObjectAttribute = DataObjectAttributes.name;
709     params = params.withOrderByAttribute(dataObjectAttribute, true);
710     var actual = dao.findByCollectionByNeo4jIds(100L, params);
711     verify(session).query(DataObject.class, query, paramsMap);
712     verify(session).query(DataObject.class, query, paramsMap);
713     assertEquals(List.of(d2), actual);
714   }
715 
716   @Test
717   public void findByParentByShepardIdsTestOrderByNameDesc() {
718     var c1 = new Collection(100L);
719     c1.setShepardId(1001L);
720     var c2 = new Collection(200L);
721     c2.setShepardId(2001L);
722     var d1 = new DataObject(1L);
723     d1.setShepardId(11L);
724     var d2 = new DataObject(2L);
725     d2.setShepardId(21L);
726     var d3 = new DataObject(3L);
727     d3.setShepardId(31L);
728     var d4 = new DataObject(4L);
729     d4.setShepardId(41L);
730     var d5 = new DataObject(5L);
731     d5.setShepardId(51L);
732     d1.setCollection(c1);
733     d2.setCollection(c1);
734     d2.setParent(d1);
735     d3.setCollection(c2);
736     d3.setParent(d1);
737     d4.setParent(d1);
738     d5.setCollection(c1);
739     d5.setParent(d2);
740     Map<String, Object> paramsMap = new HashMap<>();
741     paramsMap.put("name", null);
742 
743     String query =
744       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
745       CypherQueryHelper.getVersionHeadPart("v") +
746       " WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
747     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
748 
749     var params = new QueryParamHelper().withParentId(d1.getShepardId());
750     var dataObjectAttribute = DataObjectAttributes.name;
751     params = params.withOrderByAttribute(dataObjectAttribute, true);
752     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
753     verify(session).query(DataObject.class, query, paramsMap);
754     verify(session).query(DataObject.class, query, paramsMap);
755     assertEquals(List.of(d2), actual);
756   }
757 
758   @Test
759   public void findWithoutParentTest() {
760     var c1 = new Collection(100L);
761     var c2 = new Collection(200L);
762     var d1 = new DataObject(1L);
763     var d2 = new DataObject(2L);
764     var d3 = new DataObject(3L);
765     var d4 = new DataObject(4L);
766     var d5 = new DataObject(5L);
767     d1.setCollection(c1);
768     d2.setCollection(c1);
769     d2.setParent(d1);
770     d2.setDeleted(true);
771     d3.setCollection(c2);
772     d3.setParent(d1);
773     d4.setParent(d1);
774     d5.setCollection(c1);
775     d5.setParent(d2);
776     Map<String, Object> paramsMap = new HashMap<>();
777     paramsMap.put("name", null);
778 
779     String query =
780       """
781       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
782       WHERE ID(c)=100 AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) WITH d \
783       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
784       RETURN d, nodes(path), relationships(path)""";
785     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
786 
787     var params = new QueryParamHelper().withParentId(-1L);
788     var actual = dao.findByCollectionByNeo4jIds(100L, params);
789     verify(session).query(DataObject.class, query, paramsMap);
790     assertEquals(List.of(d1, d5), actual);
791   }
792 
793   @Test
794   public void findWithoutParentByShepardIdsTest() {
795     var c1 = new Collection(100L);
796     c1.setShepardId(1001L);
797     var c2 = new Collection(200L);
798     c2.setShepardId(2001L);
799     var d1 = new DataObject(1L);
800     d1.setShepardId(11L);
801     var d2 = new DataObject(2L);
802     d2.setShepardId(21L);
803     var d3 = new DataObject(3L);
804     d3.setShepardId(31L);
805     var d4 = new DataObject(4L);
806     d4.setShepardId(41L);
807     var d5 = new DataObject(5L);
808     d5.setShepardId(51L);
809     d1.setCollection(c1);
810     d2.setCollection(c1);
811     d2.setParent(d1);
812     d2.setDeleted(true);
813     d3.setCollection(c2);
814     d3.setParent(d1);
815     d4.setParent(d1);
816     d5.setCollection(c1);
817     d5.setParent(d2);
818     Map<String, Object> paramsMap = new HashMap<>();
819     paramsMap.put("name", null);
820 
821     String query =
822       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
823       CypherQueryHelper.getVersionHeadPart("v") +
824       " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
825     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
826 
827     var params = new QueryParamHelper().withParentId(-1L);
828     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
829     verify(session).query(DataObject.class, query, paramsMap);
830     assertEquals(List.of(d1, d5), actual);
831   }
832 
833   @Test
834   public void findWithoutParentByShepardIdsTestOrderByNameDesc() {
835     var c1 = new Collection(100L);
836     c1.setShepardId(1001L);
837     var c2 = new Collection(200L);
838     c2.setShepardId(2001L);
839     var d1 = new DataObject(1L);
840     d1.setShepardId(11L);
841     var d2 = new DataObject(2L);
842     d2.setShepardId(21L);
843     var d3 = new DataObject(3L);
844     d3.setShepardId(31L);
845     var d4 = new DataObject(4L);
846     d4.setShepardId(41L);
847     var d5 = new DataObject(5L);
848     d5.setShepardId(51L);
849     d1.setCollection(c1);
850     d2.setCollection(c1);
851     d2.setParent(d1);
852     d3.setCollection(c2);
853     d3.setParent(d1);
854     d4.setParent(d1);
855     d5.setCollection(c1);
856     d5.setParent(d2);
857     Map<String, Object> paramsMap = new HashMap<>();
858     paramsMap.put("name", null);
859 
860     String query =
861       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
862       CypherQueryHelper.getVersionHeadPart("v") +
863       " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
864     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
865 
866     var params = new QueryParamHelper().withParentId(-1L);
867     var dataObjectAttribute = DataObjectAttributes.name;
868     params = params.withOrderByAttribute(dataObjectAttribute, true);
869     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
870     verify(session).query(DataObject.class, query, paramsMap);
871     assertEquals(List.of(d1), actual);
872   }
873 
874   @Test
875   public void findWithoutParentTestOrderByNameDesc() {
876     var c1 = new Collection(100L);
877     var c2 = new Collection(200L);
878     var d1 = new DataObject(1L);
879     var d2 = new DataObject(2L);
880     var d3 = new DataObject(3L);
881     var d4 = new DataObject(4L);
882     var d5 = new DataObject(5L);
883     d1.setCollection(c1);
884     d2.setCollection(c1);
885     d2.setParent(d1);
886     d3.setCollection(c2);
887     d3.setParent(d1);
888     d4.setParent(d1);
889     d5.setCollection(c1);
890     d5.setParent(d2);
891     Map<String, Object> paramsMap = new HashMap<>();
892     paramsMap.put("name", null);
893 
894     String query =
895       """
896       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
897       WHERE ID(c)=100 AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) \
898       WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
899       RETURN d, nodes(path), relationships(path)""";
900     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
901 
902     var params = new QueryParamHelper().withParentId(-1L);
903     var dataObjectAttribute = DataObjectAttributes.name;
904     params = params.withOrderByAttribute(dataObjectAttribute, true);
905     var actual = dao.findByCollectionByNeo4jIds(100L, params);
906     verify(session).query(DataObject.class, query, paramsMap);
907     assertEquals(List.of(d1), actual);
908   }
909 
910   @Test
911   public void findByParentAndNameTest() {
912     var c1 = new Collection(100L);
913     var d1 = new DataObject(1L);
914     var d2 = new DataObject(2L);
915     var d3 = new DataObject(3L);
916     d1.setCollection(c1);
917     d2.setCollection(c1);
918     d2.setParent(d1);
919     d2.setName("Yes");
920     d3.setCollection(c1);
921     d3.setParent(d1);
922     d3.setName("No");
923     Map<String, Object> paramsMap = Map.of("name", "Yes");
924 
925     String query =
926       """
927       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })\
928       <-[:has_child]-(parent:DataObject {deleted: FALSE}) WHERE ID(c)=100 AND ID(parent)=1 WITH d \
929       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
930       RETURN d, nodes(path), relationships(path)""";
931     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
932 
933     var params = new QueryParamHelper().withParentId(1L).withName("Yes");
934     var actual = dao.findByCollectionByNeo4jIds(100L, params);
935     verify(session).query(DataObject.class, query, paramsMap);
936     assertEquals(List.of(d2), actual);
937   }
938 
939   @Test
940   public void findByParentAndNameByShepardIdsTest() {
941     var c1 = new Collection(100L);
942     c1.setShepardId(1001L);
943     var d1 = new DataObject(1L);
944     d1.setShepardId(11L);
945     var d2 = new DataObject(2L);
946     d2.setShepardId(21L);
947     var d3 = new DataObject(3L);
948     d3.setShepardId(31L);
949     d1.setCollection(c1);
950     d2.setCollection(c1);
951     d2.setParent(d1);
952     d2.setName("Yes");
953     d3.setCollection(c1);
954     d3.setParent(d1);
955     d3.setName("No");
956     Map<String, Object> paramsMap = Map.of("name", "Yes");
957 
958     String query =
959       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
960       CypherQueryHelper.getVersionHeadPart("v") +
961       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
962     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
963 
964     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withName("Yes");
965     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
966     verify(session).query(DataObject.class, query, paramsMap);
967     assertEquals(List.of(d2), actual);
968   }
969 
970   @Test
971   public void findByParentAndNameTestOrderByNameDesc() {
972     var c1 = new Collection(100L);
973     var d1 = new DataObject(1L);
974     var d2 = new DataObject(2L);
975     var d3 = new DataObject(3L);
976     d1.setCollection(c1);
977     d2.setCollection(c1);
978     d2.setParent(d1);
979     d2.setName("Yes");
980     d3.setCollection(c1);
981     d3.setParent(d1);
982     d3.setName("No");
983     Map<String, Object> paramsMap = Map.of("name", "Yes");
984 
985     String query =
986       """
987       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })\
988       <-[:has_child]-(parent:DataObject {deleted: FALSE}) \
989       WHERE ID(c)=100 AND ID(parent)=1 WITH d ORDER BY toLower(d.name) DESC \
990       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
991       RETURN d, nodes(path), relationships(path)""";
992     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
993 
994     var params = new QueryParamHelper().withParentId(1L).withName("Yes");
995     var dataObjectAttribute = DataObjectAttributes.name;
996     params = params.withOrderByAttribute(dataObjectAttribute, true);
997     var actual = dao.findByCollectionByNeo4jIds(100L, params);
998     verify(session).query(DataObject.class, query, paramsMap);
999     assertEquals(List.of(d2), actual);
1000   }
1001 
1002   @Test
1003   public void findByParentAndNameByShepardIdsTestOrderByNameDesc() {
1004     var c1 = new Collection(100L);
1005     c1.setShepardId(1001L);
1006     var d1 = new DataObject(1L);
1007     d1.setShepardId(11L);
1008     var d2 = new DataObject(2L);
1009     d2.setShepardId(21L);
1010     var d3 = new DataObject(3L);
1011     d3.setShepardId(31L);
1012     d1.setCollection(c1);
1013     d2.setCollection(c1);
1014     d2.setParent(d1);
1015     d2.setName("Yes");
1016     d3.setCollection(c1);
1017     d3.setParent(d1);
1018     d3.setName("No");
1019     Map<String, Object> paramsMap = Map.of("name", "Yes");
1020 
1021     String query =
1022       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
1023       CypherQueryHelper.getVersionHeadPart("v") +
1024       " WITH d ORDER BY toLower(d.name) DESC MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1025     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3));
1026 
1027     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withName("Yes");
1028     var dataObjectAttribute = DataObjectAttributes.name;
1029     params = params.withOrderByAttribute(dataObjectAttribute, true);
1030     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1031     verify(session).query(DataObject.class, query, paramsMap);
1032     assertEquals(List.of(d2), actual);
1033   }
1034 
1035   @Test
1036   public void findByParentAndPageTest() {
1037     var c1 = new Collection(100L);
1038     var d1 = new DataObject(1L);
1039     var d2 = new DataObject(2L);
1040     d1.setCollection(c1);
1041     d2.setCollection(c1);
1042     d2.setParent(d1);
1043     d2.setName("Yes");
1044     Map<String, Object> paramsMap = new HashMap<>();
1045     paramsMap.put("name", null);
1046     paramsMap.put("offset", 300);
1047     paramsMap.put("size", 100);
1048 
1049     String query =
1050       """
1051       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
1052       <-[:has_child]-(parent:DataObject {deleted: FALSE}) \
1053       WHERE ID(c)=100 AND ID(parent)=1 WITH d SKIP $offset LIMIT $size \
1054       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1055       RETURN d, nodes(path), relationships(path)""";
1056     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
1057 
1058     var params = new QueryParamHelper().withParentId(1L).withPageAndSize(3, 100);
1059     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1060     verify(session).query(DataObject.class, query, paramsMap);
1061     assertEquals(List.of(d2), actual);
1062   }
1063 
1064   @Test
1065   public void findByParentAndPageByShepardIdsTest() {
1066     var c1 = new Collection(100L);
1067     c1.setShepardId(1001L);
1068     var d1 = new DataObject(1L);
1069     d1.setShepardId(11L);
1070     var d2 = new DataObject(2L);
1071     d2.setShepardId(21L);
1072     d1.setCollection(c1);
1073     d2.setCollection(c1);
1074     d2.setParent(d1);
1075     d2.setName("Yes");
1076     Map<String, Object> paramsMap = new HashMap<>();
1077     paramsMap.put("name", null);
1078     paramsMap.put("offset", 300);
1079     paramsMap.put("size", 100);
1080 
1081     String query =
1082       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
1083       CypherQueryHelper.getVersionHeadPart("v") +
1084       " WITH d SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1085     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
1086 
1087     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withPageAndSize(3, 100);
1088     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1089     verify(session).query(DataObject.class, query, paramsMap);
1090     assertEquals(List.of(d2), actual);
1091   }
1092 
1093   @Test
1094   public void findByParentAndPageTestOrderByNameDesc() {
1095     var c1 = new Collection(100L);
1096     var d1 = new DataObject(1L);
1097     var d2 = new DataObject(2L);
1098     d1.setCollection(c1);
1099     d2.setCollection(c1);
1100     d2.setParent(d1);
1101     d2.setName("Yes");
1102     Map<String, Object> paramsMap = new HashMap<>();
1103     paramsMap.put("name", null);
1104     paramsMap.put("offset", 300);
1105     paramsMap.put("size", 100);
1106 
1107     String query =
1108       """
1109       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
1110       <-[:has_child]-(parent:DataObject {deleted: FALSE}) WHERE ID(c)=100 AND ID(parent)=1 \
1111       WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size \
1112       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1113       RETURN d, nodes(path), relationships(path)""";
1114     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
1115 
1116     var params = new QueryParamHelper().withParentId(1L).withPageAndSize(3, 100);
1117     var dataObjectAttribute = DataObjectAttributes.name;
1118     params = params.withOrderByAttribute(dataObjectAttribute, true);
1119     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1120     verify(session).query(DataObject.class, query, paramsMap);
1121     assertEquals(List.of(d2), actual);
1122   }
1123 
1124   @Test
1125   public void findByParentAndPageByShepardIdsTestOrderByNameDesc() {
1126     var c1 = new Collection(100L);
1127     c1.setShepardId(1001L);
1128     var d1 = new DataObject(1L);
1129     d1.setShepardId(11L);
1130     var d2 = new DataObject(2L);
1131     d2.setShepardId(21L);
1132     d1.setCollection(c1);
1133     d2.setCollection(c1);
1134     d2.setParent(d1);
1135     d2.setName("Yes");
1136     Map<String, Object> paramsMap = new HashMap<>();
1137     paramsMap.put("name", null);
1138     paramsMap.put("offset", 300);
1139     paramsMap.put("size", 100);
1140 
1141     String query =
1142       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
1143       CypherQueryHelper.getVersionHeadPart("v") +
1144       " WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1145     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2));
1146 
1147     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withPageAndSize(3, 100);
1148     var dataObjectAttribute = DataObjectAttributes.name;
1149     params = params.withOrderByAttribute(dataObjectAttribute, true);
1150     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1151     verify(session).query(DataObject.class, query, paramsMap);
1152     assertEquals(List.of(d2), actual);
1153   }
1154 
1155   @Test
1156   public void findByParentAndPageAndNameTest() {
1157     var c1 = new Collection(100L);
1158     var d1 = new DataObject(1L);
1159     var d2 = new DataObject(2L);
1160     var d3 = new DataObject(3L);
1161     var d4 = new DataObject(4L);
1162     d1.setCollection(c1);
1163     d2.setCollection(c1);
1164     d2.setParent(d1);
1165     d2.setName("Yes");
1166     d3.setCollection(c1);
1167     d3.setParent(d1);
1168     d3.setName("No");
1169     Map<String, Object> paramsMap = new HashMap<>();
1170     paramsMap.put("name", "Yes");
1171     paramsMap.put("offset", 300);
1172     paramsMap.put("size", 100);
1173 
1174     String query =
1175       """
1176       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })\
1177       <-[:has_child]-(parent:DataObject {deleted: FALSE}) \
1178       WHERE ID(c)=100 AND ID(parent)=1 WITH d SKIP $offset LIMIT $size \
1179       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1180       RETURN d, nodes(path), relationships(path)""";
1181     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4));
1182 
1183     var params = new QueryParamHelper().withParentId(1L).withPageAndSize(3, 100).withName("Yes");
1184     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1185     verify(session).query(DataObject.class, query, paramsMap);
1186     assertEquals(List.of(d2), actual);
1187   }
1188 
1189   @Test
1190   public void findByParentAndPageAndNameByShepardIdsTest() {
1191     var c1 = new Collection(100L);
1192     c1.setShepardId(1001L);
1193     var d1 = new DataObject(1L);
1194     d1.setShepardId(11L);
1195     var d2 = new DataObject(2L);
1196     d2.setShepardId(21L);
1197     var d3 = new DataObject(3L);
1198     d3.setShepardId(31L);
1199     var d4 = new DataObject(4L);
1200     d4.setShepardId(41L);
1201     d1.setCollection(c1);
1202     d2.setCollection(c1);
1203     d2.setParent(d1);
1204     d2.setName("Yes");
1205     d3.setCollection(c1);
1206     d3.setParent(d1);
1207     d3.setName("No");
1208     Map<String, Object> paramsMap = new HashMap<>();
1209     paramsMap.put("name", "Yes");
1210     paramsMap.put("offset", 300);
1211     paramsMap.put("size", 100);
1212 
1213     String query =
1214       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
1215       CypherQueryHelper.getVersionHeadPart("v") +
1216       " WITH d SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1217     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4));
1218 
1219     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withPageAndSize(3, 100).withName("Yes");
1220     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1221     verify(session).query(DataObject.class, query, paramsMap);
1222     assertEquals(List.of(d2), actual);
1223   }
1224 
1225   @Test
1226   public void findByParentAndPageAndNameTestOrderByNameDesc() {
1227     var c1 = new Collection(100L);
1228     var d1 = new DataObject(1L);
1229     var d2 = new DataObject(2L);
1230     var d3 = new DataObject(3L);
1231     var d4 = new DataObject(4L);
1232     d1.setCollection(c1);
1233     d2.setCollection(c1);
1234     d2.setParent(d1);
1235     d2.setName("Yes");
1236     d3.setCollection(c1);
1237     d3.setParent(d1);
1238     d3.setName("No");
1239     Map<String, Object> paramsMap = new HashMap<>();
1240     paramsMap.put("name", "Yes");
1241     paramsMap.put("offset", 300);
1242     paramsMap.put("size", 100);
1243 
1244     String query =
1245       """
1246       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })\
1247       <-[:has_child]-(parent:DataObject {deleted: FALSE}) WHERE ID(c)=100 AND ID(parent)=1 \
1248       WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size \
1249       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1250       RETURN d, nodes(path), relationships(path)""";
1251     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4));
1252 
1253     var params = new QueryParamHelper().withParentId(1L).withPageAndSize(3, 100).withName("Yes");
1254     var dataObjectAttribute = DataObjectAttributes.name;
1255     params = params.withOrderByAttribute(dataObjectAttribute, true);
1256     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1257     verify(session).query(DataObject.class, query, paramsMap);
1258     assertEquals(List.of(d2), actual);
1259   }
1260 
1261   @Test
1262   public void findByParentAndPageAndNameByShepardIdsTestOrderByNameDesc() {
1263     var c1 = new Collection(100L);
1264     c1.setShepardId(1001L);
1265     var d1 = new DataObject(1L);
1266     d1.setShepardId(11L);
1267     var d2 = new DataObject(2L);
1268     d2.setShepardId(21L);
1269     var d3 = new DataObject(3L);
1270     d3.setShepardId(31L);
1271     var d4 = new DataObject(4L);
1272     d4.setShepardId(41L);
1273     d1.setCollection(c1);
1274     d2.setCollection(c1);
1275     d2.setParent(d1);
1276     d2.setName("Yes");
1277     d3.setCollection(c1);
1278     d3.setParent(d1);
1279     d3.setName("No");
1280     Map<String, Object> paramsMap = new HashMap<>();
1281     paramsMap.put("name", "Yes");
1282     paramsMap.put("offset", 300);
1283     paramsMap.put("size", 100);
1284 
1285     String query =
1286       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE })<-[:has_child]-(parent:DataObject {deleted: FALSE, shepardId: 11}) WHERE c.shepardId=1001 AND " +
1287       CypherQueryHelper.getVersionHeadPart("v") +
1288       " WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1289     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4));
1290 
1291     var params = new QueryParamHelper().withParentId(d1.getShepardId()).withPageAndSize(3, 100).withName("Yes");
1292     var dataObjectAttribute = DataObjectAttributes.name;
1293     params = params.withOrderByAttribute(dataObjectAttribute, true);
1294     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1295     verify(session).query(DataObject.class, query, paramsMap);
1296     assertEquals(List.of(d2), actual);
1297   }
1298 
1299   @Test
1300   public void findWithoutParentByPageAndNameTest() {
1301     var c1 = new Collection(100L);
1302     var c2 = new Collection(200L);
1303     var d1 = new DataObject(1L);
1304     var d2 = new DataObject(2L);
1305     var d3 = new DataObject(3L);
1306     var d4 = new DataObject(4L);
1307     var d5 = new DataObject(5L);
1308     d1.setCollection(c1);
1309     d1.setName("Yes");
1310     d2.setCollection(c1);
1311     d2.setName("No");
1312     d3.setCollection(c2);
1313     d3.setName("Yes");
1314     d4.setCollection(c1);
1315     d4.setParent(d1);
1316     d4.setName("Yes");
1317     Map<String, Object> paramsMap = new HashMap<>();
1318     paramsMap.put("name", "Yes");
1319     paramsMap.put("offset", 300);
1320     paramsMap.put("size", 100);
1321 
1322     String query =
1323       """
1324       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) \
1325       WHERE ID(c)=100 AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) \
1326       WITH d SKIP $offset LIMIT $size \
1327       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1328       RETURN d, nodes(path), relationships(path)""";
1329     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
1330 
1331     var params = new QueryParamHelper().withParentId(-1L).withPageAndSize(3, 100).withName("Yes");
1332     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1333     verify(session).query(DataObject.class, query, paramsMap);
1334     assertEquals(List.of(d1), actual);
1335   }
1336 
1337   @Test
1338   public void findWithoutParentByPageAndNameByShepardIdsTest() {
1339     var c1 = new Collection(100L);
1340     c1.setShepardId(1001L);
1341     var c2 = new Collection(200L);
1342     c2.setShepardId(2001L);
1343     var d1 = new DataObject(1L);
1344     d1.setShepardId(11L);
1345     var d2 = new DataObject(2L);
1346     d2.setShepardId(21L);
1347     var d3 = new DataObject(3L);
1348     d3.setShepardId(31L);
1349     var d4 = new DataObject(4L);
1350     d4.setShepardId(41L);
1351     var d5 = new DataObject(5L);
1352     d5.setShepardId(51L);
1353     d1.setCollection(c1);
1354     d1.setName("Yes");
1355     d2.setCollection(c1);
1356     d2.setName("No");
1357     d3.setCollection(c2);
1358     d3.setName("Yes");
1359     d4.setCollection(c1);
1360     d4.setParent(d1);
1361     d4.setName("Yes");
1362     Map<String, Object> paramsMap = new HashMap<>();
1363     paramsMap.put("name", "Yes");
1364     paramsMap.put("offset", 300);
1365     paramsMap.put("size", 100);
1366 
1367     String query =
1368       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
1369       CypherQueryHelper.getVersionHeadPart("v") +
1370       " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) WITH d SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1371     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
1372 
1373     var params = new QueryParamHelper().withParentId(-1L).withPageAndSize(3, 100).withName("Yes");
1374     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1375     verify(session).query(DataObject.class, query, paramsMap);
1376     assertEquals(List.of(d1), actual);
1377   }
1378 
1379   @Test
1380   public void findWithoutParentByPageAndNameTestOrderByNameDesc() {
1381     var c1 = new Collection(100L);
1382     var c2 = new Collection(200L);
1383     var d1 = new DataObject(1L);
1384     var d2 = new DataObject(2L);
1385     var d3 = new DataObject(3L);
1386     var d4 = new DataObject(4L);
1387     var d5 = new DataObject(5L);
1388     d1.setCollection(c1);
1389     d1.setName("Yes");
1390     d2.setCollection(c1);
1391     d2.setName("No");
1392     d3.setCollection(c2);
1393     d3.setName("Yes");
1394     d4.setCollection(c1);
1395     d4.setParent(d1);
1396     d4.setName("Yes");
1397     Map<String, Object> paramsMap = new HashMap<>();
1398     paramsMap.put("name", "Yes");
1399     paramsMap.put("offset", 300);
1400     paramsMap.put("size", 100);
1401 
1402     String query =
1403       """
1404       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) \
1405       WHERE ID(c)=100 AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) \
1406       WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size \
1407       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1408       RETURN d, nodes(path), relationships(path)""";
1409     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
1410 
1411     var params = new QueryParamHelper().withParentId(-1L).withPageAndSize(3, 100).withName("Yes");
1412     var dataObjectAttribute = DataObjectAttributes.name;
1413     params = params.withOrderByAttribute(dataObjectAttribute, true);
1414     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1415     verify(session).query(DataObject.class, query, paramsMap);
1416     assertEquals(List.of(d1), actual);
1417   }
1418 
1419   @Test
1420   public void findWithoutParentByPageAndNameByShepardIdsTestOrderByNameDesc() {
1421     var c1 = new Collection(100L);
1422     c1.setShepardId(1001L);
1423     var c2 = new Collection(200L);
1424     c2.setShepardId(2001L);
1425     var d1 = new DataObject(1L);
1426     d1.setShepardId(11L);
1427     var d2 = new DataObject(2L);
1428     d2.setShepardId(21L);
1429     var d3 = new DataObject(3L);
1430     d3.setShepardId(31L);
1431     var d4 = new DataObject(4L);
1432     d4.setShepardId(41L);
1433     var d5 = new DataObject(5L);
1434     d5.setShepardId(51L);
1435     d1.setCollection(c1);
1436     d1.setName("Yes");
1437     d2.setCollection(c1);
1438     d2.setName("No");
1439     d3.setCollection(c2);
1440     d3.setName("Yes");
1441     d4.setCollection(c1);
1442     d4.setParent(d1);
1443     d4.setName("Yes");
1444     Map<String, Object> paramsMap = new HashMap<>();
1445     paramsMap.put("name", "Yes");
1446     paramsMap.put("offset", 300);
1447     paramsMap.put("size", 100);
1448 
1449     String query =
1450       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { name : $name, deleted: FALSE }) WHERE c.shepardId=1001 AND " +
1451       CypherQueryHelper.getVersionHeadPart("v") +
1452       " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE})) WITH d ORDER BY toLower(d.name) DESC SKIP $offset LIMIT $size MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1453     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d1, d2, d3, d4, d5));
1454 
1455     var params = new QueryParamHelper().withParentId(-1L).withPageAndSize(3, 100).withName("Yes");
1456     var dataObjectAttribute = DataObjectAttributes.name;
1457     params = params.withOrderByAttribute(dataObjectAttribute, true);
1458     var actual = dao.findByCollectionByShepardIds(c1.getShepardId(), params);
1459     verify(session).query(DataObject.class, query, paramsMap);
1460     assertEquals(List.of(d1), actual);
1461   }
1462 
1463   @Test
1464   public void findByPredecessor() {
1465     var c = new Collection(100L);
1466     var pre = new DataObject(201L);
1467     var d = new DataObject(200L);
1468     pre.setCollection(c);
1469     pre.addSuccessor(d);
1470     d.addPredecessor(pre);
1471     d.setCollection(c);
1472 
1473     var query =
1474       """
1475       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
1476       <-[:has_successor]-(predecessor:DataObject {deleted: FALSE}) \
1477       WHERE ID(c)=100 AND ID(predecessor)=201 WITH d \
1478       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1479       RETURN d, nodes(path), relationships(path)""";
1480     Map<String, Object> paramsMap = new HashMap<>();
1481     paramsMap.put("name", null);
1482 
1483     var params = new QueryParamHelper().withPredecessorId(201L);
1484     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, pre));
1485 
1486     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1487     verify(session).query(DataObject.class, query, paramsMap);
1488     assertEquals(List.of(d), actual);
1489   }
1490 
1491   @Test
1492   public void findByPredecessorByShepardIds() {
1493     var c = new Collection(100L);
1494     c.setShepardId(1001L);
1495     var pre = new DataObject(201L);
1496     pre.setShepardId(2011L);
1497     var d = new DataObject(200L);
1498     d.setShepardId(2001L);
1499     pre.setCollection(c);
1500     pre.addSuccessor(d);
1501     d.addPredecessor(pre);
1502     d.setCollection(c);
1503 
1504     String query =
1505       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })<-[:has_successor]-(predecessor:DataObject {deleted: FALSE, shepardId: 2011}) WHERE c.shepardId=1001 AND " +
1506       CypherQueryHelper.getVersionHeadPart("v") +
1507       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1508     Map<String, Object> paramsMap = new HashMap<>();
1509     paramsMap.put("name", null);
1510 
1511     var params = new QueryParamHelper().withPredecessorId(pre.getShepardId());
1512     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, pre));
1513 
1514     var actual = dao.findByCollectionByShepardIds(c.getShepardId(), params);
1515     verify(session).query(DataObject.class, query, paramsMap);
1516     assertEquals(List.of(d), actual);
1517   }
1518 
1519   @Test
1520   public void findWithoutPredecessor() {
1521     var c = new Collection(100L);
1522     var d = new DataObject(200L);
1523     var d2 = new DataObject(201L);
1524     d.setCollection(c);
1525     d.addSuccessor(d2);
1526     d2.addPredecessor(d2);
1527     d2.setCollection(c);
1528 
1529     var query =
1530       """
1531       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
1532       WHERE ID(c)=100 AND NOT EXISTS((d)<-[:has_successor]-(:DataObject {deleted: FALSE})) WITH d \
1533       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1534       RETURN d, nodes(path), relationships(path)""";
1535     Map<String, Object> paramsMap = new HashMap<>();
1536     paramsMap.put("name", null);
1537 
1538     var params = new QueryParamHelper().withPredecessorId(-1L);
1539     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, d2));
1540 
1541     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1542     verify(session).query(DataObject.class, query, paramsMap);
1543     assertEquals(List.of(d), actual);
1544   }
1545 
1546   @Test
1547   public void findWithoutPredecessorWithShepardIds() {
1548     var c = new Collection(100L);
1549     c.setShepardId(1001L);
1550     var d = new DataObject(200L);
1551     d.setShepardId(2001L);
1552     var d2 = new DataObject(201L);
1553     d2.setShepardId(2011L);
1554     d.setCollection(c);
1555     d.addSuccessor(d2);
1556     d2.addPredecessor(d2);
1557     d2.setCollection(c);
1558 
1559     String query =
1560       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
1561       CypherQueryHelper.getVersionHeadPart("v") +
1562       " AND NOT EXISTS((d)<-[:has_successor]-(:DataObject {deleted: FALSE})) WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1563     Map<String, Object> paramsMap = new HashMap<>();
1564     paramsMap.put("name", null);
1565 
1566     var params = new QueryParamHelper().withPredecessorId(-1L);
1567     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, d2));
1568 
1569     var actual = dao.findByCollectionByShepardIds(c.getShepardId(), params);
1570     verify(session).query(DataObject.class, query, paramsMap);
1571     assertEquals(List.of(d), actual);
1572   }
1573 
1574   @Test
1575   public void findBySuccessor() {
1576     var c = new Collection(100L);
1577     var suc = new DataObject(201L);
1578     var d = new DataObject(200L);
1579     suc.setCollection(c);
1580     suc.addPredecessor(d);
1581     d.addSuccessor(suc);
1582     d.setCollection(c);
1583 
1584     var query =
1585       """
1586       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })\
1587       -[:has_successor]->(successor:DataObject {deleted: FALSE}) \
1588       WHERE ID(c)=100 AND ID(successor)=201 WITH d \
1589       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1590       RETURN d, nodes(path), relationships(path)""";
1591     Map<String, Object> paramsMap = new HashMap<>();
1592     paramsMap.put("name", null);
1593 
1594     var params = new QueryParamHelper().withSuccessorId(201L);
1595     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, suc));
1596 
1597     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1598     verify(session).query(DataObject.class, query, paramsMap);
1599     assertEquals(List.of(d), actual);
1600   }
1601 
1602   @Test
1603   public void findBySuccessorByShepardIds() {
1604     var c = new Collection(100L);
1605     c.setShepardId(1001L);
1606     var suc = new DataObject(201L);
1607     suc.setShepardId(2011L);
1608     var d = new DataObject(200L);
1609     d.setShepardId(2001L);
1610     suc.setCollection(c);
1611     suc.addPredecessor(d);
1612     d.addSuccessor(suc);
1613     d.setCollection(c);
1614 
1615     String query =
1616       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE })-[:has_successor]->(successor:DataObject {deleted: FALSE, shepardId: 2011}) WHERE c.shepardId=1001 AND " +
1617       CypherQueryHelper.getVersionHeadPart("v") +
1618       " WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1619     Map<String, Object> paramsMap = new HashMap<>();
1620     paramsMap.put("name", null);
1621 
1622     var params = new QueryParamHelper().withSuccessorId(suc.getShepardId());
1623     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, suc));
1624 
1625     var actual = dao.findByCollectionByShepardIds(c.getShepardId(), params);
1626     verify(session).query(DataObject.class, query, paramsMap);
1627     assertEquals(List.of(d), actual);
1628   }
1629 
1630   @Test
1631   public void findWithoutSuccessor() {
1632     var c = new Collection(100L);
1633     var d = new DataObject(200L);
1634     var d2 = new DataObject(201L);
1635     d2.setCollection(c);
1636     d2.addSuccessor(d);
1637     d.addPredecessor(d2);
1638     d.setCollection(c);
1639 
1640     var query =
1641       """
1642       MATCH (c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) \
1643       WHERE ID(c)=100 AND NOT EXISTS((d)-[:has_successor]->(:DataObject {deleted: FALSE})) WITH d \
1644       MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL \
1645       RETURN d, nodes(path), relationships(path)""";
1646     Map<String, Object> paramsMap = new HashMap<>();
1647     paramsMap.put("name", null);
1648 
1649     var params = new QueryParamHelper().withSuccessorId(-1L);
1650     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, d2));
1651 
1652     var actual = dao.findByCollectionByNeo4jIds(100L, params);
1653     verify(session).query(DataObject.class, query, paramsMap);
1654     assertEquals(List.of(d), actual);
1655   }
1656 
1657   @Test
1658   public void findWithoutSuccessorWithShepardIds() {
1659     var c = new Collection(100L);
1660     c.setShepardId(1001L);
1661     var d = new DataObject(200L);
1662     d.setShepardId(2001L);
1663     var d2 = new DataObject(201L);
1664     d2.setShepardId(2011L);
1665     d2.setCollection(c);
1666     d2.addSuccessor(d);
1667     d.addPredecessor(d2);
1668     d.setCollection(c);
1669 
1670     String query =
1671       "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->(d:DataObject { deleted: FALSE }) WHERE c.shepardId=1001 AND " +
1672       CypherQueryHelper.getVersionHeadPart("v") +
1673       " AND NOT EXISTS((d)-[:has_successor]->(:DataObject {deleted: FALSE})) WITH d MATCH path=(d)-[*0..1]-(n) WHERE n.deleted = FALSE OR n.deleted IS NULL RETURN d, nodes(path), relationships(path)";
1674     Map<String, Object> paramsMap = new HashMap<>();
1675     paramsMap.put("name", null);
1676 
1677     var params = new QueryParamHelper().withSuccessorId(-1L);
1678     when(session.query(DataObject.class, query, paramsMap)).thenReturn(List.of(d, d2));
1679 
1680     var actual = dao.findByCollectionByShepardIds(c.getShepardId(), params);
1681     verify(session).query(DataObject.class, query, paramsMap);
1682     assertEquals(List.of(d), actual);
1683   }
1684 
1685   @Test
1686   public void deleteDataObjectTest() {
1687     DataObjectDAO spy = spy(DataObjectDAO.class);
1688 
1689     var dataObject = new DataObject(1L);
1690     var user = new User("bob");
1691     var date = new Date();
1692 
1693     var updated = new DataObject(1L);
1694     updated.setUpdatedBy(user);
1695     updated.setUpdatedAt(date);
1696     updated.setDeleted(true);
1697 
1698     doReturn(dataObject).when(spy).findByNeo4jId(1L);
1699     doReturn(updated).when(spy).createOrUpdate(updated);
1700     doReturn(true)
1701       .when(spy)
1702       .runQuery(
1703         "MATCH (d:DataObject) WHERE ID(d) = 1 OPTIONAL MATCH (d)-[:has_reference]->(r:BasicReference) " +
1704         "FOREACH (n in [d,r] | SET n.deleted = true)",
1705         Collections.emptyMap()
1706       );
1707 
1708     var result = spy.deleteDataObjectByNeo4jId(1L, user, date);
1709     verify(spy).createOrUpdate(updated);
1710     assertTrue(result);
1711   }
1712 
1713   @Test
1714   public void deleteDataObjectByShepardIdTest() {
1715     DataObjectDAO spy = spy(DataObjectDAO.class);
1716 
1717     var dataObject = new DataObject(1L);
1718     dataObject.setShepardId(11L);
1719     var user = new User("bob");
1720     var date = new Date();
1721 
1722     var updated = new DataObject(1L);
1723     updated.setShepardId(11L);
1724     updated.setUpdatedBy(user);
1725     updated.setUpdatedAt(date);
1726     updated.setDeleted(true);
1727 
1728     doReturn(dataObject).when(spy).findByShepardId(dataObject.getShepardId());
1729     doReturn(updated).when(spy).createOrUpdate(updated);
1730     doReturn(true)
1731       .when(spy)
1732       .runQuery(
1733         "MATCH (d:DataObject) WHERE ID(d) = 1 OPTIONAL MATCH (d)-[:has_reference]->(r:BasicReference) FOREACH (n in [d,r] | SET n.deleted = true)",
1734         Collections.emptyMap()
1735       );
1736 
1737     var result = spy.deleteDataObjectByShepardId(dataObject.getShepardId(), user, date);
1738     verify(spy).createOrUpdate(updated);
1739     assertTrue(result);
1740   }
1741 
1742   @Test
1743   public void getDataObjectsByQueryTest() {
1744     DataObjectDAO spy = spy(DataObjectDAO.class);
1745 
1746     var dataObject = new DataObject(1L);
1747 
1748     doReturn(List.of(dataObject)).when(spy).findByQuery("query", Collections.emptyMap());
1749 
1750     var result = spy.getDataObjectsByQuery("query");
1751     assertEquals(List.of(dataObject), result);
1752   }
1753 }