1 package de.dlr.shepard.context.collection.daos;
2
3 import de.dlr.shepard.auth.users.entities.User;
4 import de.dlr.shepard.common.util.Constants;
5 import de.dlr.shepard.common.util.CypherQueryHelper;
6 import de.dlr.shepard.common.util.QueryParamHelper;
7 import de.dlr.shepard.context.collection.entities.DataObject;
8 import de.dlr.shepard.context.version.daos.VersionableEntityDAO;
9 import jakarta.enterprise.context.RequestScoped;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Date;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.UUID;
17 import java.util.stream.StreamSupport;
18
19 @RequestScoped
20 public class DataObjectDAO extends VersionableEntityDAO<DataObject> {
21
22 @Override
23 public Class<DataObject> getEntityType() {
24 return DataObject.class;
25 }
26
27
28
29
30
31
32
33
34 public List<DataObject> findByCollectionByNeo4jIds(long collectionId, QueryParamHelper params) {
35 Map<String, Object> paramsMap = new HashMap<>();
36 paramsMap.put("name", params.getName());
37 if (params.hasPagination()) {
38 paramsMap.put("offset", params.getPagination().getOffset());
39 paramsMap.put("size", params.getPagination().getSize());
40 }
41 String match =
42 "MATCH (c:Collection)-[hdo:has_dataobject]->" +
43 CypherQueryHelper.getObjectPart("d", "DataObject", params.hasName());
44 String where = " WHERE ID(c)=" + collectionId;
45
46 if (params.hasParentId()) {
47 if (params.getParentId() == -1) {
48 where += " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE}))";
49 } else {
50 match += "<-[:has_child]-(parent:DataObject {deleted: FALSE})";
51 where += " AND ID(parent)=" + params.getParentId();
52 }
53 }
54
55 if (params.hasPredecessorId()) {
56 if (params.getPredecessorId() == -1) {
57 where += " AND NOT EXISTS((d)<-[:has_successor]-(:DataObject {deleted: FALSE}))";
58 } else {
59 match += "<-[:has_successor]-(predecessor:DataObject {deleted: FALSE})";
60 where += " AND ID(predecessor)=" + params.getPredecessorId();
61 }
62 }
63 if (params.hasSuccessorId()) {
64 if (params.getSuccessorId() == -1) {
65 where += " AND NOT EXISTS((d)-[:has_successor]->(:DataObject {deleted: FALSE}))";
66 } else {
67 match += "-[:has_successor]->(successor:DataObject {deleted: FALSE})";
68 where += " AND ID(successor)=" + params.getSuccessorId();
69 }
70 }
71
72 String query = match + where + " WITH d";
73 if (params.hasOrderByAttribute()) {
74 query += " " + CypherQueryHelper.getOrderByPart("d", params.getOrderByAttribute(), params.getOrderDesc());
75 }
76 if (params.hasPagination()) {
77 query += " " + CypherQueryHelper.getPaginationPart();
78 }
79 query += " " + CypherQueryHelper.getReturnPart("d");
80 var result = new ArrayList<DataObject>();
81 for (var obj : findByQuery(query, paramsMap)) {
82 List<DataObject> parentList = obj.getParent() != null ? List.of(obj.getParent()) : Collections.emptyList();
83 if (
84 matchCollection(obj, collectionId) &&
85 matchName(obj, params.getName()) &&
86 matchRelated(parentList, params.getParentId()) &&
87 matchRelated(obj.getSuccessors(), params.getSuccessorId()) &&
88 matchRelated(obj.getPredecessors(), params.getPredecessorId())
89 ) {
90 result.add(obj);
91 }
92 }
93
94 return result;
95 }
96
97 public List<DataObject> findByCollectionByShepardIds(
98 long collectionShepardId,
99 QueryParamHelper paramsWithShepardIds
100 ) {
101 return findByCollectionByShepardIds(collectionShepardId, paramsWithShepardIds, null);
102 }
103
104
105
106
107 public void deleteHasSuccessorRelation(long predecessorShepardId, long successorShepardId) {
108 deleteRelation(
109 predecessorShepardId,
110 successorShepardId,
111 getEntityType().getSimpleName(),
112 getEntityType().getSimpleName(),
113 Constants.HAS_SUCCESSOR
114 );
115 }
116
117
118
119
120 public void deleteHasChildRelation(long parentShepardId, long childShepardId) {
121 deleteRelation(
122 parentShepardId,
123 childShepardId,
124 getEntityType().getSimpleName(),
125 getEntityType().getSimpleName(),
126 Constants.HAS_CHILD
127 );
128 }
129
130
131
132
133
134
135
136
137 public List<DataObject> findByCollectionByShepardIds(
138 long collectionShepardId,
139 QueryParamHelper paramsWithShepardIds,
140 UUID versionUID
141 ) {
142 Map<String, Object> paramsMap = new HashMap<>();
143 paramsMap.put("name", paramsWithShepardIds.getName());
144 if (paramsWithShepardIds.hasPagination()) {
145 paramsMap.put("offset", paramsWithShepardIds.getPagination().getOffset());
146 paramsMap.put("size", paramsWithShepardIds.getPagination().getSize());
147 }
148 String match =
149 "MATCH (v:Version)<-[:has_version]-(c:Collection)-[hdo:has_dataobject]->" +
150 CypherQueryHelper.getObjectPart("d", "DataObject", paramsWithShepardIds.hasName());
151 String where = " WHERE c." + Constants.SHEPARD_ID + "=" + collectionShepardId + " AND ";
152
153 if (versionUID == null) where = where + CypherQueryHelper.getVersionHeadPart("v");
154
155 else where = where + CypherQueryHelper.getVersionPart("v", versionUID);
156 if (paramsWithShepardIds.hasParentId()) {
157 if (paramsWithShepardIds.getParentId() == -1) {
158 where += " AND NOT EXISTS((d)<-[:has_child]-(:DataObject {deleted: FALSE}))";
159 } else {
160 match +=
161 "<-[:has_child]-(parent:DataObject {deleted: FALSE, " +
162 Constants.SHEPARD_ID +
163 ": " +
164 paramsWithShepardIds.getParentId() +
165 "})";
166 }
167 }
168
169 if (paramsWithShepardIds.hasPredecessorId()) {
170 if (paramsWithShepardIds.getPredecessorId() == -1) {
171 where += " AND NOT EXISTS((d)<-[:has_successor]-(:DataObject {deleted: FALSE}))";
172 } else {
173 match +=
174 "<-[:has_successor]-(predecessor:DataObject {deleted: FALSE, " +
175 Constants.SHEPARD_ID +
176 ": " +
177 paramsWithShepardIds.getPredecessorId() +
178 "})";
179 }
180 }
181 if (paramsWithShepardIds.hasSuccessorId()) {
182 if (paramsWithShepardIds.getSuccessorId() == -1) {
183 where += " AND NOT EXISTS((d)-[:has_successor]->(:DataObject {deleted: FALSE}))";
184 } else {
185 match +=
186 "-[:has_successor]->(successor:DataObject {deleted: FALSE, " +
187 Constants.SHEPARD_ID +
188 ": " +
189 paramsWithShepardIds.getSuccessorId() +
190 "})";
191 }
192 }
193
194 String query = match + where + " WITH d";
195 if (paramsWithShepardIds.hasOrderByAttribute()) {
196 query +=
197 " " +
198 CypherQueryHelper.getOrderByPart(
199 "d",
200 paramsWithShepardIds.getOrderByAttribute(),
201 paramsWithShepardIds.getOrderDesc()
202 );
203 }
204 if (paramsWithShepardIds.hasPagination()) {
205 query += " " + CypherQueryHelper.getPaginationPart();
206 }
207 query += " " + CypherQueryHelper.getReturnPart("d");
208 var result = new ArrayList<DataObject>();
209 for (var obj : findByQuery(query, paramsMap)) {
210 List<DataObject> parentList = obj.getParent() != null ? List.of(obj.getParent()) : Collections.emptyList();
211 if (
212 matchCollectionByShepardId(obj, collectionShepardId) &&
213 matchName(obj, paramsWithShepardIds.getName()) &&
214 matchRelatedByShepardId(parentList, paramsWithShepardIds.getParentId()) &&
215 matchRelatedByShepardId(obj.getSuccessors(), paramsWithShepardIds.getSuccessorId()) &&
216 matchRelatedByShepardId(obj.getPredecessors(), paramsWithShepardIds.getPredecessorId())
217 ) {
218 result.add(obj);
219 }
220 }
221
222 return result;
223 }
224
225
226
227
228
229
230
231
232
233 public boolean deleteDataObjectByNeo4jId(long id, User updatedBy, Date updatedAt) {
234 var dataObject = findByNeo4jId(id);
235 dataObject.setUpdatedBy(updatedBy);
236 dataObject.setUpdatedAt(updatedAt);
237 dataObject.setDeleted(true);
238 createOrUpdate(dataObject);
239 String query = String.format(
240 "MATCH (d:DataObject) WHERE ID(d) = %d OPTIONAL MATCH (d)-[:has_reference]->(r:BasicReference) " +
241 "FOREACH (n in [d,r] | SET n.deleted = true)",
242 id
243 );
244 var result = runQuery(query, Collections.emptyMap());
245 return result;
246 }
247
248
249
250
251
252
253
254
255
256 public boolean deleteDataObjectByShepardId(long shepardId, User updatedBy, Date updatedAt) {
257 DataObject dataObject = findByShepardId(shepardId);
258 dataObject.setUpdatedBy(updatedBy);
259 dataObject.setUpdatedAt(updatedAt);
260 dataObject.setDeleted(true);
261 createOrUpdate(dataObject);
262 String query = String.format(
263 "MATCH (d:DataObject) WHERE ID(d) = %d OPTIONAL MATCH (d)-[:has_reference]->(r:BasicReference) " +
264 "FOREACH (n in [d,r] | SET n.deleted = true)",
265 dataObject.getId()
266 );
267 var result = runQuery(query, Collections.emptyMap());
268 return result;
269 }
270
271 private boolean matchName(DataObject obj, String name) {
272 return name == null || name.equalsIgnoreCase(obj.getName());
273 }
274
275 private boolean matchRelated(List<DataObject> related, Long id) {
276 if (id == null) {
277 return true;
278 } else if (id == -1) {
279
280 return related.stream().allMatch(DataObject::isDeleted);
281 } else {
282
283 return related.stream().anyMatch(d -> !d.isDeleted() && d.getId().equals(id));
284 }
285 }
286
287 private boolean matchRelatedByShepardId(List<DataObject> related, Long shepardId) {
288 if (shepardId == null) {
289 return true;
290 } else if (shepardId == -1) {
291
292 return related.stream().allMatch(DataObject::isDeleted);
293 } else {
294
295 return related.stream().anyMatch(d -> !d.isDeleted() && d.getShepardId().equals(shepardId));
296 }
297 }
298
299 private boolean matchCollection(DataObject obj, long collectionId) {
300 return obj.getCollection() != null && obj.getCollection().getId().equals(collectionId);
301 }
302
303 private boolean matchCollectionByShepardId(DataObject obj, long collectionShepardId) {
304 return obj.getCollection() != null && obj.getCollection().getShepardId().equals(collectionShepardId);
305 }
306
307 public List<DataObject> getDataObjectsByQuery(String query) {
308 var queryResult = findByQuery(query, Collections.emptyMap());
309 List<DataObject> ret = StreamSupport.stream(queryResult.spliterator(), false).toList();
310 return ret;
311 }
312 }