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